package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.formula.constant.Constant;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.elasticsearch.constant.EsNormalConstant;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.SubFormPoJo;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.parent.help.CommonPermissionHelp;
import com.xbongbong.paas.help.FormDataHelp;
import com.xbongbong.paas.help.PaasFormHelp;
import com.xbongbong.paas.help.UserHelp;
import com.xbongbong.paas.log.constant.CrmLogMemoConstant;
import com.xbongbong.paas.manager.feign.AliyuncallCenterFeignClient;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.AliyunCallCenterPojo;
import com.xbongbong.paas.pojo.CallLogExplainPojo;
import com.xbongbong.paas.pojo.CallLogPojo;
import com.xbongbong.paas.pojo.DuYanTranscriptionItemPojo;
import com.xbongbong.paas.pojo.ItemDataPoJo;
import com.xbongbong.paas.pojo.RecordContentPojo;
import com.xbongbong.paas.pojo.SummaryDataPoJo;
import com.xbongbong.paas.pojo.dto.AddCommunicateDTO;
import com.xbongbong.paas.pojo.dto.AliyunBatchUpdateCallRecordDTO;
import com.xbongbong.paas.pojo.dto.AliyunBatchUpdateDTO;
import com.xbongbong.paas.pojo.dto.AliyunCallBatchInsertDTO;
import com.xbongbong.paas.pojo.dto.AliyunCallCenterListDTO;
import com.xbongbong.paas.pojo.dto.AliyunCallCenterModelDTO;
import com.xbongbong.paas.pojo.dto.AliyunCallGetCallListDTO;
import com.xbongbong.paas.pojo.dto.AliyunCallRecordConditionReqDTO;
import com.xbongbong.paas.pojo.dto.AliyunCallSaveCommunicateReqDTO;
import com.xbongbong.paas.pojo.dto.AliyunCallUserInfoConditionReqDTO;
import com.xbongbong.paas.pojo.dto.AliyunCallcenterRecentlyRecordDTO;
import com.xbongbong.paas.pojo.dto.AliyunListSyncCallRecordDTO;
import com.xbongbong.paas.pojo.dto.AliyunListUnSyncCallRecordDTO;
import com.xbongbong.paas.pojo.dto.AliyunUpdateCallRecordModelDTO;
import com.xbongbong.paas.pojo.dto.AutoCommunicateDTO;
import com.xbongbong.paas.pojo.dto.BlockRuleRemindDTO;
import com.xbongbong.paas.pojo.dto.CallAudioTranslateDTO;
import com.xbongbong.paas.pojo.dto.CallCallLogListDTO;
import com.xbongbong.paas.pojo.dto.CallCallLogSaveDTO;
import com.xbongbong.paas.pojo.dto.CallCenterAccountUserInfoDTO;
import com.xbongbong.paas.pojo.dto.CallCenterFindRefDTO;
import com.xbongbong.paas.pojo.dto.CallCenterModuleDTO;
import com.xbongbong.paas.pojo.dto.CallContentLogSaveDTO;
import com.xbongbong.paas.pojo.dto.CallMissedCallListDTO;
import com.xbongbong.paas.pojo.dto.CallRecordConfigDTO;
import com.xbongbong.paas.pojo.dto.CallRecordDynamicDTO;
import com.xbongbong.paas.pojo.dto.CallRecordLogSaveDTO;
import com.xbongbong.paas.pojo.dto.CallRecordStaticDTO;
import com.xbongbong.paas.pojo.dto.ExternalCallRecordDTO;
import com.xbongbong.paas.pojo.dto.ExternalSumCallRecordDTO;
import com.xbongbong.paas.pojo.dto.UinSumCallRecordDTO;
import com.xbongbong.paas.pojo.dto.UinYunCallRecordDTO;
import com.xbongbong.paas.pojo.dto.UserAndDepartmentGetDTO;
import com.xbongbong.paas.pojo.dto.YunCallDepAllUserListDTO;
import com.xbongbong.paas.pojo.dto.YunCallPageRecordDTO;
import com.xbongbong.paas.pojo.dto.YunCallRecordDTO;
import com.xbongbong.paas.pojo.vo.AddCommunicateVO;
import com.xbongbong.paas.pojo.vo.AliyunCallGetCallListVO;
import com.xbongbong.paas.pojo.vo.AliyunCallUserInfoConditionVO;
import com.xbongbong.paas.pojo.vo.AliyunCallcenterListVO;
import com.xbongbong.paas.pojo.vo.AliyunCallcenterRecentlyRecordVO;
import com.xbongbong.paas.pojo.vo.BlockRuleRemindVO;
import com.xbongbong.paas.pojo.vo.CallAudioTranslateVO;
import com.xbongbong.paas.pojo.vo.CallCallLogSaveVO;
import com.xbongbong.paas.pojo.vo.CallCenterAccountUserInfoVO;
import com.xbongbong.paas.pojo.vo.CallCenterConfigVO;
import com.xbongbong.paas.pojo.vo.CallCenterModuleVO;
import com.xbongbong.paas.pojo.vo.CallCenterOrgGetByCorpIdVO;
import com.xbongbong.paas.pojo.vo.CallLogListVO;
import com.xbongbong.paas.pojo.vo.CallLogRecordStaticVO;
import com.xbongbong.paas.pojo.vo.CallRecordConfigVO;
import com.xbongbong.paas.pojo.vo.DuYanCallLogResponseParamVO;
import com.xbongbong.paas.pojo.vo.DuYanCallLogVO;
import com.xbongbong.paas.pojo.vo.DuYanTranscriptionResponseVO;
import com.xbongbong.paas.pojo.vo.DuYanTranscriptionVO;
import com.xbongbong.paas.pojo.vo.ExternalSumCallRecordVO;
import com.xbongbong.paas.pojo.vo.UinSumCallRecordVO;
import com.xbongbong.paas.pojo.vo.YunCallRecordPageVO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisConstant;
import com.xbongbong.paas.service.AudioFileService;
import com.xbongbong.paas.service.AudioTranslatorService;
import com.xbongbong.paas.service.CallCenterAccountService;
import com.xbongbong.paas.service.CallCenterCallLogService;
import com.xbongbong.paas.service.CallCenterCommonService;
import com.xbongbong.paas.service.CallCenterConfigService;
import com.xbongbong.paas.service.CallCenterOrganizationService;
import com.xbongbong.paas.service.CallCenterTeamService;
import com.xbongbong.paas.service.DuYanHttpService;
import com.xbongbong.paas.service.PaasFormService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.helper.ThreadPoolHelper;
import com.xbongbong.paas.toolbox.thread.TransmittableThreadLocalUtil;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseDTO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.parent.explain.FormDataDetailFormExplainHandleName;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.enums.CallCenterTypeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.CallCenterErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ClueErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainDTO;
import com.xbongbong.pro.formexplain.pojo.vo.HandlerExplainVO;
import com.xbongbong.pro.label.pojo.dto.LabelListDTO;
import com.xbongbong.pro.label.pojo.dto.LabelShowVO;
import com.xbongbong.pro.permission.pojo.dto.VerifyUpdatePermissionDTO;
import com.xbongbong.pro.permission.pojo.dto.VerifyViewPermissionDTO;
import com.xbongbong.pro.service.toolbox.statistic.help.SystemChartHelp;
import com.xbongbong.pro.statistic.result.pojo.ElasticAggsPojo;
import com.xbongbong.pro.statistic.result.pojo.TotalAndAggPojo;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.constant.callcenter.CallCenterCallBackConstant;
import com.xbongbong.saas.constant.callcenter.CallCenterConstant;
import com.xbongbong.saas.constant.callcenter.DuYanConstant;
import com.xbongbong.saas.domain.entity.CallCenterCallLogEntity;
import com.xbongbong.saas.domain.entity.CallCenterTeamEntity;
import com.xbongbong.saas.domain.entity.UserTeamEntity;
import com.xbongbong.saas.domain.entity.ext.ClueEntityExt;
import com.xbongbong.saas.domain.entity.ext.ContactEntityExt;
import com.xbongbong.saas.domain.entity.ext.CustomerEntityExt;
import com.xbongbong.saas.enums.AliyunCallCenterResultEnum;
import com.xbongbong.saas.enums.CallCenterCallLogCallSourceEnum;
import com.xbongbong.saas.enums.CallLogResultEnum;
import com.xbongbong.saas.enums.CallLogTypeEnum;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.ListBusinessTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.base.ManagementBaseEnum;
import com.xbongbong.saas.enums.business.ClueEnum;
import com.xbongbong.saas.enums.business.ContactEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.help.DetailTabDataPermissionHelp;
import com.xbongbong.saas.help.LabelHelp;
import com.xbongbong.saas.help.SaasGetHelp;
import com.xbongbong.saas.model.CallCenterCallLogModel;
import com.xbongbong.saas.model.ClueModel;
import com.xbongbong.saas.model.ClueUserModel;
import com.xbongbong.saas.model.ContactModel;
import com.xbongbong.saas.model.ContactUserModel;
import com.xbongbong.saas.model.CustomerModel;
import com.xbongbong.saas.model.CustomerUserModel;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.PaasFormDataModel;
import com.xbongbong.saas.service.LabelService;
import com.xbongbong.saas.service.UserTeamService;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.CompanyConfigEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.help.ProPermissionHelp;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.UserModel;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.collapse.CollapseBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.StringJoiner;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.existsQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchPhraseQuery;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author youli.chen
 * @version v1.0
 * @description: 话务中心通话记录业务层接口实现类
 * @date 2019/2/18 22:11
 * @since v1.0
 */
@Service("callCenterCallLogService")
public class CallCenterCallLogServiceImpl implements CallCenterCallLogService {

    private static final Logger LOG = LoggerFactory.getLogger(CallCenterCallLogServiceImpl.class);

    @Resource
    private ThreadPoolTaskExecutor callCenterThreadPool;
    @Resource
    private CallCenterCallLogModel callCenterCallLogModel;
    @Resource
    private CallCenterConfigService callCenterConfigService;
    @Resource
    private CustomerModel customerModel;
    @Resource
    private ContactModel contactModel;
    @Resource
    private CallCenterOrganizationService callCenterOrganizationService;
    @Resource
    private CallCenterCommonService callCenterCommonService;
    @Resource
    private DuYanHttpService duYanHttpService;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private UserModel userModel;
    @Resource
    private CallCenterAccountService callCenterAccountService;
    @Resource
    private CallCenterTeamService callCenterTeamService;
    @Resource
    private AudioFileService audioFileService;
    @Resource
    private AudioTranslatorService xunFeiAudioTranslatorService;
    @Resource
    private AudioTranslatorService aliyunAudioTranslatorService;
    @Resource
    private EsHelper esHelper;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private PaasFormService paasFormService;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private ClueModel clueModel;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private LabelHelp labelHelp;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private UserHelp userHelp;
    @Resource
    private PaasFormHelp paasFormHelp;
    @Resource
    private FormDataDetailFormExplainHandleName formDataDetailFormExplainHandleName;
    @Resource
    private PaasFormDataModel paasFormDataModel;
    @Resource
    private SaasGetHelp saasGetHelp;
    @Resource
    LabelService  labelService;
    @Resource
    AliyuncallCenterFeignClient aliyuncallCenterFeignClient;

    @Resource
    private ProBaseConfig proBaseConfig;

    @Resource
    private CompanyConfigModel companyConfigModel;

    @Resource
    private UserTeamService userTeamService;

    @Resource
    private CommonPermissionHelp commonPermissionHelp;
    @Resource
    private ProPermissionHelp proPermissionHelp;
    @Resource
    private IndexTypeModel indexTypeModel;
    @Resource
    private DetailTabDataPermissionHelp detailTabDataPermissionHelp;
    @Resource
    private SystemChartHelp systemChartHelp;
    @Resource
    private FormDataHelp formDataHelp;
    @Resource
    private CustomerUserModel customerUserModel;
    @Resource
    private ClueUserModel clueUserModel;
    @Resource
    private ContactUserModel contactUserModel;

    /**
     * 保存通话记录
     *
     * @param callCallLogSaveDTO 保存通话记录入参
     * @return CallCallLogSaveVO  保存通话记录回参
     * @throws XbbException
     */
    @Override
    public XbbResponse<CallCallLogSaveVO> callLogSave(CallCallLogSaveDTO callCallLogSaveDTO) throws XbbException {
        CallCallLogSaveVO callCallLogSaveVO = new CallCallLogSaveVO();
        String corpid = callCallLogSaveDTO.getCorpid();
        String userId = callCallLogSaveDTO.getUserId();
        Integer moduleType = callCallLogSaveDTO.getModuleType();
        XbbResponse<CallCenterConfigVO> configResponse = callCenterConfigService.getByCorpId(corpid, moduleType);
        CallCenterConfigVO callCenterConfigVO = configResponse.getResult();
        if (callCenterConfigVO == null) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301051);
        }
        String anotherPhoneNum = callCallLogSaveDTO.getAnotherPhoneNum();
        // 客户
        CustomerEntityExt cusEntityExt = customerModel.getByPhone(corpid, anotherPhoneNum);
        ContactEntityExt contactEntityExt = null;
        String customerId = "";
        if (cusEntityExt != null) {
            customerId = String.valueOf(cusEntityExt.getId());
            // 兼容，防止并发，通话记录重新查询
            callCallLogSaveDTO.setRefId(cusEntityExt.getId());
            callCallLogSaveDTO.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(cusEntityExt.getData(), CustomerManagementEnum.NAME.getAttr(), ""));
            callCallLogSaveDTO.setRefType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
        } else if (cusEntityExt == null){
            // 联系人
            contactEntityExt = contactModel.getByPhone(corpid, anotherPhoneNum);
            if(contactEntityExt != null){
                Long contactId = contactEntityExt.getId();
                callCallLogSaveDTO.setRefId(contactId);
                callCallLogSaveDTO.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(contactEntityExt.getData(), ContactEnum.NAME.getAttr(), ""));
                callCallLogSaveDTO.setRefType(XbbRefTypeEnum.CONTACT.getCode());
            }
        } else if (cusEntityExt == null && contactEntityExt == null){
            // 线索
            ClueEntityExt clueEntityExt = clueModel.getByPhone(corpid, anotherPhoneNum);
            if(clueEntityExt != null){
                Long clueId = clueEntityExt.getId();
                callCallLogSaveDTO.setRefId(clueId);
                callCallLogSaveDTO.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(clueEntityExt.getData(), ClueEnum.COMPANY_NAME.getAttr(), ""));
                callCallLogSaveDTO.setRefType(XbbRefTypeEnum.CLUE.getCode());
            } else {
                callCallLogSaveDTO.setRefId(0L);
                callCallLogSaveDTO.setRefName(String.format(I18nMessageUtil.getMessage(I18nStringConstant.STRANGE_NUMBER) + "【%s】", anotherPhoneNum));
                callCallLogSaveDTO.setRefType(CallCenterTypeEnum.UNKNOWN.getCode());
            }
        }

        if (callCallLogSaveDTO.getEndTime() != null) {
            if (callCallLogSaveDTO.getEndTime() < callCallLogSaveDTO.getStartTime()) {
                throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301052);
            }
        }
        if (callCallLogSaveDTO.getRefId() == null || callCallLogSaveDTO.getRefType() == null) {
            callCallLogSaveDTO.setRefId(0L);
            callCallLogSaveDTO.setRefType(CallCenterTypeEnum.UNKNOWN.getCode());
        } else if (StringUtil.isEmpty(callCallLogSaveDTO.getRefName())) {
            // 前端端告知了对象类型，但是未告知对象名
            if (callCallLogSaveDTO.getRefId() != null) {
                callCallLogSaveDTO.setRefName(getRefName(corpid, callCallLogSaveDTO.getRefId(), callCallLogSaveDTO.getRefType()));
            }
        }

        if (StringUtil.isEmpty(callCallLogSaveDTO.getRefName())) {
            // 对象名未知，一般是查询不到通话的对象，是一个陌生号码
            callCallLogSaveDTO.setRefName(callCallLogSaveDTO.getAnotherPhoneNum());
        }
        // 封装用的保存的对象
        CallCenterCallLogEntity saveEntity = new CallCenterCallLogEntity();
        // 移动端通话记录
        //只有度言呼叫中心的数据需要同步,逍邦呼叫中心跳过 youli.chen
        if (callCallLogSaveDTO.getResult() != null &&
                callCallLogSaveDTO.getResult() == CallLogResultEnum.UN_SYNCED.getCode() &&
                moduleType == CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode()) {

            // 同步当前用户近1天的所有移动端的通话记录
            syncTodayMobileCallLog(corpid, userId, moduleType);
            // 移动端的通话记录需要同步
            BeanUtils.copyProperties(callCallLogSaveDTO, saveEntity);
            saveEntity.setCallTime(callCallLogSaveDTO.getStartTime());
            saveEntity.setDuration(0);
            saveEntity.setRingTime(0);
        } else {
            // 通话记录数据封装
            duYanCallLog(saveEntity, callCallLogSaveDTO);
        }
        if (callCallLogSaveDTO.getRefId() != null) {
            saveEntity.setRefId(callCallLogSaveDTO.getRefId());
        }
        saveEntity.setRefType(callCallLogSaveDTO.getRefType());
        saveEntity.setRefName(callCallLogSaveDTO.getRefName());
        saveEntity.setCallUuid(callCallLogSaveDTO.getUuid());

        initRecordUrl(saveEntity);

        // 防重复提交  拼接saas数据库旧索引（增加一个录音地址）
        String md5Hex = corpid + "_" + userId + "_" + callCallLogSaveDTO.getAnotherPhoneNum() + "_" + saveEntity.getCallTime() + "_" + saveEntity.getRecordUrl();
        boolean concurrentLock = paasRedisHelper.checkConcurrentLock(md5Hex);
        if (!concurrentLock) {
            return new XbbResponse<>(callCallLogSaveVO);
        }
        Integer saveResult = callCenterCallLogModel.insert(saveEntity);

        callCallLogSaveVO = communicateAndCallNumPer(saveEntity, saveResult, callCallLogSaveVO,
                callCallLogSaveDTO, callCenterConfigVO, customerId);
        return new XbbResponse<>(callCallLogSaveVO);
    }

    @Override
    public Boolean callRecordLogSave(CallRecordLogSaveDTO callRecordLogSaveDTO) throws XbbException {
        //LOG.info("通话记录....." + JSON.toJSONString(callRecordLogSaveDTO));
        List<CallContentLogSaveDTO> callContentLogSaveDTOList = callRecordLogSaveDTO.getContent();
        if (callContentLogSaveDTOList == null || callContentLogSaveDTOList.size() == 0) {
            return Boolean.FALSE;
        }
        CallContentLogSaveDTO callContentLogSaveDTO = callContentLogSaveDTOList.get(0);
        CallCallLogSaveVO callCallLogSaveVO = new CallCallLogSaveVO();
        CallCallLogSaveDTO callCallLogSaveDTO =new CallCallLogSaveDTO();
        callCallLogSaveDTO.setModuleType(XbbRefTypeEnum.CALL_CENTER_XBB.getCode());
        callCallLogSaveDTO.setRefId(callContentLogSaveDTO.getRefId());
        callCallLogSaveDTO.setRefName(callContentLogSaveDTO.getRefName());
        callCallLogSaveDTO.setRefType(callContentLogSaveDTO.getRefType());
        callCallLogSaveDTO.setCallId(callContentLogSaveDTO.getCallId());
        callCallLogSaveDTO.setUserId(callContentLogSaveDTO.getUserWid());
        callCallLogSaveDTO.setCcId(callContentLogSaveDTO.getCcid());
        callCallLogSaveDTO.setCorpid(callContentLogSaveDTO.getPid());
        callCallLogSaveDTO.setType(Integer.valueOf(callContentLogSaveDTO.getCallDirection()));
        callCallLogSaveDTO.setPlatform(StringConstant.PLATFORM_WEB);
        if (Objects.isNull(callContentLogSaveDTO.getTxcospath())) {
            callCallLogSaveDTO.setRecordUrl(proBaseConfig.getCallCenterViewurl() + callContentLogSaveDTO.getRecordFileName());
        } else {
            callCallLogSaveDTO.setRecordUrl(proBaseConfig.getCallCenterViewurl() + proBaseConfig.getCallCenterBucketName() + "/" + callContentLogSaveDTO.getRecordFileName());
        }
        callCallLogSaveDTO.setStartTime(DateUtil.getInt(callContentLogSaveDTO.getStartTime(),DateUtil.SDF));
        callCallLogSaveDTO.setAnswerTime(DateUtil.getInt(callContentLogSaveDTO.getAnswerTime(),DateUtil.SDF));
        callCallLogSaveDTO.setConnectTime(DateUtil.getInt(callContentLogSaveDTO.getStartTime(),DateUtil.SDF));
        callCallLogSaveDTO.setEndTime(DateUtil.getInt(callContentLogSaveDTO.getEndTime(),DateUtil.SDF));
        if (StringUtil.isNotEmpty(callContentLogSaveDTO.getDuration())) {
            callCallLogSaveDTO.setDuration(Integer.valueOf(callContentLogSaveDTO.getDuration()));
        }

        String corpid = callCallLogSaveDTO.getCorpid();
        String userId = callCallLogSaveDTO.getUserId();
        Integer moduleType = callContentLogSaveDTO.getModuleType();
        XbbResponse<CallCenterConfigVO> configResponse = callCenterConfigService.getByCorpId(corpid, moduleType);
        CallCenterConfigVO callCenterConfigVO = configResponse.getResult();
        if (callCenterConfigVO == null) {
            LOG.info("当前公司没有开呼叫中心");
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301051);
        }
        //0:呼入 1:呼出(另一方号码)
        String anotherPhoneNum = null;
        if (Objects.equals(callContentLogSaveDTO.getCallDirection(), "0")) {
            anotherPhoneNum = callContentLogSaveDTO.getCaller();
            callCallLogSaveDTO.setAnotherPhoneNum(anotherPhoneNum);
            callCallLogSaveDTO.setAgentPhoneNum(callContentLogSaveDTO.getCallee());
        }else {
            anotherPhoneNum = callContentLogSaveDTO.getCallee();
            callCallLogSaveDTO.setAnotherPhoneNum(anotherPhoneNum);
            callCallLogSaveDTO.setAgentPhoneNum(callContentLogSaveDTO.getCaller());
        }

        String customerId = "";

        //拨号传入自定义参数目的：处理截图过后的电话号码和具体业务里保存的电话号码对应不上
        Integer refType = 0;
        Long refId = 0L;
        if (Objects.nonNull(callContentLogSaveDTO.getExtraparam()) && Objects.nonNull(JSON.parseObject(JSON.toJSONString(callContentLogSaveDTO.getExtraparam())).get("refId"))
                && Objects.nonNull(JSON.parseObject(JSON.toJSONString(callContentLogSaveDTO.getExtraparam())).get("refType"))
                && Objects.equals(callContentLogSaveDTO.getCallDirection(),"1")) {
            JSONObject extraParamJson = JSON.parseObject(JSON.toJSONString(callContentLogSaveDTO.getExtraparam()));
            refType = Integer.valueOf(extraParamJson.get("refType").toString());
            refId = Long.valueOf(extraParamJson.get("refId").toString());
        }

        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(refType);
        switch (xbbRefTypeEnum) {
            case CUSTOMER_MANAGEMENT:
                CustomerEntityExt customerEntity = customerModel.getByKey(refId, corpid);
                if (Objects.nonNull(customerEntity)) {
                    customerId = String.valueOf(customerEntity.getId());
                    // 兼容，防止并发，通话记录重新查询
                    callCallLogSaveDTO.setRefId(customerEntity.getId());
                    callCallLogSaveDTO.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(customerEntity.getData(), CustomerManagementEnum.NAME.getAttr(), ""));
                    callCallLogSaveDTO.setRefType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                }
                break;
            case CONTACT:
                ContactEntityExt contactEntity = contactModel.getByKey(refId, corpid);
                if (Objects.nonNull(contactEntity)) {
                    Long contactId = contactEntity.getId();
                    callCallLogSaveDTO.setRefId(contactId);
                    callCallLogSaveDTO.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(contactEntity.getData(), ContactEnum.NAME.getAttr(), ""));
                    callCallLogSaveDTO.setRefType(XbbRefTypeEnum.CONTACT.getCode());
                }
                break;
            case CLUE:
                ClueEntityExt clueEntity = clueModel.getByKey(refId, corpid);
                if (clueEntity != null) {
                    Long clueId = clueEntity.getId();
                    callCallLogSaveDTO.setRefId(clueId);
                    callCallLogSaveDTO.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(clueEntity.getData(), ClueEnum.COMPANY_NAME.getAttr(), ""));
                    callCallLogSaveDTO.setRefType(XbbRefTypeEnum.CLUE.getCode());
                }
                break;
            default:
                // 客户
                CustomerEntityExt cusEntityExt = customerModel.getByPhone(corpid, anotherPhoneNum);
                ContactEntityExt contactEntityExt = null;
                if (cusEntityExt != null) {
                    customerId = String.valueOf(cusEntityExt.getId());
                    // 兼容，防止并发，通话记录重新查询
                    callCallLogSaveDTO.setRefId(cusEntityExt.getId());
                    callCallLogSaveDTO.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(cusEntityExt.getData(), CustomerManagementEnum.NAME.getAttr(), ""));
                    callCallLogSaveDTO.setRefType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                } else if (cusEntityExt == null) {
                    // 联系人
                    contactEntityExt = contactModel.getByPhone(corpid, anotherPhoneNum);
                    if(contactEntityExt != null) {
                        Long contactId = contactEntityExt.getId();
                        callCallLogSaveDTO.setRefId(contactId);
                        callCallLogSaveDTO.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(contactEntityExt.getData(), ContactEnum.NAME.getAttr(), ""));
                        callCallLogSaveDTO.setRefType(XbbRefTypeEnum.CONTACT.getCode());
                    }
                } else if (cusEntityExt == null && contactEntityExt == null) {
                    // 线索
                    ClueEntityExt clueEntityExt = clueModel.getByPhone(corpid, anotherPhoneNum);
                    if(clueEntityExt != null){
                        Long clueId = clueEntityExt.getId();
                        callCallLogSaveDTO.setRefId(clueId);
                        callCallLogSaveDTO.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(clueEntityExt.getData(), ClueEnum.COMPANY_NAME.getAttr(), ""));
                        callCallLogSaveDTO.setRefType(XbbRefTypeEnum.CLUE.getCode());
                    } else {
                        callCallLogSaveDTO.setRefId(0L);
                        callCallLogSaveDTO.setRefName(String.format(I18nMessageUtil.getMessage(I18nStringConstant.STRANGE_NUMBER) + "【%s】", anotherPhoneNum));
                        callCallLogSaveDTO.setRefType(CallCenterTypeEnum.UNKNOWN.getCode());
                    }
                }
                break;
        }

        if (callCallLogSaveDTO.getRefId() == null || callCallLogSaveDTO.getRefType() == null) {
            callCallLogSaveDTO.setRefId(0L);
            callCallLogSaveDTO.setRefType(CallCenterTypeEnum.UNKNOWN.getCode());
        } else if (StringUtil.isEmpty(callCallLogSaveDTO.getRefName())) {
            // 前端端告知了对象类型，但是未告知对象名
            if (callCallLogSaveDTO.getRefId() != null) {
                callCallLogSaveDTO.setRefName(getRefName(corpid, callCallLogSaveDTO.getRefId(), callCallLogSaveDTO.getRefType()));
            }
        }

        if (StringUtil.isEmpty(callCallLogSaveDTO.getRefName())) {
            // 对象名未知，一般是查询不到通话的对象，是一个陌生号码
            callCallLogSaveDTO.setRefName(callCallLogSaveDTO.getAnotherPhoneNum());
        }
        // 封装用的保存的对象
        CallCenterCallLogEntity saveEntity = new CallCenterCallLogEntity();
        saveEntity.setCallSource(CallCenterCallLogCallSourceEnum.CALL_CENTER.getCode());
        // 移动端通话记录
        //只有度言呼叫中心的数据需要同步,逍邦呼叫中心跳过 youli.chen
        if (callCallLogSaveDTO.getResult() != null &&
                callCallLogSaveDTO.getResult() == CallLogResultEnum.UN_SYNCED.getCode() &&
                moduleType == CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode()) {

            // 同步当前用户近1天的所有移动端的通话记录
            syncTodayMobileCallLog(corpid, userId, moduleType);
            // 移动端的通话记录需要同步
            BeanUtils.copyProperties(callCallLogSaveDTO, saveEntity);
            saveEntity.setCallTime(callCallLogSaveDTO.getStartTime());
            saveEntity.setDuration(0);
            saveEntity.setRingTime(0);
        } else {
            // 通话记录数据封装
            duYanCallLog(saveEntity, callCallLogSaveDTO);
        }
        if (callCallLogSaveDTO.getRefId() != null) {
            saveEntity.setRefId(callCallLogSaveDTO.getRefId());
        }
        saveEntity.setRefType(callCallLogSaveDTO.getRefType());
        saveEntity.setRefName(callCallLogSaveDTO.getRefName());
        saveEntity.setCallUuid(callCallLogSaveDTO.getUuid());

        //initRecordUrl(saveEntity);

        // 防重复提交  拼接saas数据库旧索引（增加一个录音地址）
        String md5Hex = corpid + "_" + userId + "_" + callCallLogSaveDTO.getAnotherPhoneNum() + "_" + saveEntity.getCallTime() + "_" + callContentLogSaveDTO.getRecordFileName();
        boolean concurrentLock = paasRedisHelper.checkConcurrentLock(md5Hex);
        if (!concurrentLock) {
            return Boolean.FALSE;
        }
        Integer saveResult = callCenterCallLogModel.insert(saveEntity);
        if (saveResult > 0) {
            callCallLogSaveVO = communicateAndCallNumPer(saveEntity, saveResult, callCallLogSaveVO,
                    callCallLogSaveDTO, callCenterConfigVO, customerId);
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 未接来电记录
     *
     * @param callMissedCallListDTO 未接来电记录入参
     * @return CallMissedCallListVO  未接来电记录回参
     * @throws XbbException
     */
    @Override
    public XbbResponse<CallLogListVO> missedCallList(CallMissedCallListDTO callMissedCallListDTO) throws XbbException {
        CallLogListVO callLogListVO = new CallLogListVO();
        String userId = callMissedCallListDTO.getUserId();
        String corpid = callMissedCallListDTO.getCorpid();
        Integer moduleType = callMissedCallListDTO.getModuleType();
        if (moduleType == null || moduleType == 0) {
            CallCenterModuleDTO callCenterModuleDTO = new CallCenterModuleDTO();
            BeanUtil.copyProperties(callMissedCallListDTO, callCenterModuleDTO);
            CallCenterModuleVO callCenterModuleVO = callCenterCommonService.module(callCenterModuleDTO);
            if (callCenterModuleVO == null) {
                throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301053);
            }
            moduleType = callCenterModuleVO.getModuleType();
        }
        if (callCenterCommonService.notCallCenterModule(moduleType)) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301029);
        }
        CallCenterAccountUserInfoDTO userInfoDTO = new CallCenterAccountUserInfoDTO();
        BeanUtils.copyProperties(callMissedCallListDTO, userInfoDTO);
        CallCenterAccountUserInfoVO userInfoVO = callCenterAccountService.getByXbbUserInfo(userInfoDTO);
        if (userInfoVO == null) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301003);
        } else if (userInfoVO.getIsAgent() == 0) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301002);
        }
        if (moduleType.equals(CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode())) {
            // 获取未接来电列表
            callLogListVO = getMissedCallLogList(corpid, moduleType, userInfoVO,
                    callMissedCallListDTO.getPage(), callMissedCallListDTO.getPageSize());
        } else if (moduleType.equals(CallCenterTypeEnum.CALL_CENTER_XBB.getCode())) {
            //初始化时获取未接来电数量
            Integer incrNumber = 0;
            if (paasRedisHelper.getValue(CallCenterConstant.CUSTOMER_MISS_CALLLOG_SUM, corpid + "_" + userId) == null) {
                incrNumber = 0;
            } else {
                incrNumber = Integer.valueOf(paasRedisHelper.getValue(CallCenterConstant.CUSTOMER_MISS_CALLLOG_SUM, corpid + "_" + userId));
            }
            callLogListVO.setTotalPages(0);
            callLogListVO.setTotalElements(incrNumber);
        }
        return new XbbResponse<>(callLogListVO);
    }

    /**
     * 防封号提醒
     *
     * @param blockRuleRemindDTO 防封号规则提醒入参
     * @return BlockRuleRemindVO  防封号规则提醒回参
     * @throws XbbException
     */
    @Override
    public XbbResponse<BlockRuleRemindVO> blockRuleRemind(BlockRuleRemindDTO blockRuleRemindDTO) throws XbbException {
        BlockRuleRemindVO blockRuleRemindVO = new BlockRuleRemindVO();
        String corpid = blockRuleRemindDTO.getCorpid();
        String ccId = blockRuleRemindDTO.getCcId();
        Integer moduleType = blockRuleRemindDTO.getModuleType();
        if(Objects.equals(moduleType, XbbRefTypeEnum.CALL_CENTER_XBB.getCode())){
            XbbResponse<CallCenterConfigVO> configResponse = callCenterConfigService.getByCorpId(corpid, moduleType);
            CallCenterConfigVO callCenterConfigVO = configResponse.getResult();
            if (callCenterConfigVO == null) {
                throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301051);
            }
            Integer callBlockInterval = callCenterConfigVO.getCallBlockInterval();
            Integer callBlockThirtyNum = callCenterConfigVO.getCallBlockThirtyNum() == null ? 0 : callCenterConfigVO.getCallBlockThirtyNum();
            Integer callBlockDayNum = callCenterConfigVO.getCallBlockDayNum();
            Integer callBlockRule = callCenterConfigVO.getCallBlockRule();

            // 自动换卡设置
            Integer callBlockThirtySwitch = callCenterConfigVO.getCallBlockThirtySwitch();
            Integer callBlockDaySwitch = callCenterConfigVO.getCallBlockDaySwitch();

            // 换卡套餐服务状态
            Integer callBlockServer = callCenterOrganizationService.callBlockServer(corpid, moduleType);
            // 套餐失效，假性关闭防封号规则
            if(!Objects.equals(callBlockServer, BasicConstant.ONE)){
                callBlockRule = BasicConstant.ZERO;
            }

            if(Objects.equals(callBlockRule, BasicConstant.ONE) && StringUtil.isNotEmpty(ccId)){
                // 时间间隔缓存
                String intervalRedisKey = corpid + "_" + ccId + "_" + "interval";
                // intervalLock == 原先设定的时间间隔(value)
                String intervalLock = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_INTERVAL_LOCK, intervalRedisKey);
                if(StringUtil.isNotEmpty(intervalLock) && !Objects.equals(callBlockInterval, BasicConstant.ZERO)){
                    Long intervalLiveTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_INTERVAL_LOCK, intervalRedisKey);
                    Integer intervalLevel = BasicConstant.THREE;

                    // 修改redis
                    if(callBlockInterval > StringUtil.toInt(intervalLock)){
                        // 重新设置规则之后，大于原先设定值时，重置value值
                        // 自定义时间间隔
                        Integer interval = callBlockInterval - StringUtil.toInt(intervalLock);
                        Integer newTime = intervalLiveTime.intValue() + interval;
                        paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_INTERVAL_LOCK, intervalRedisKey, callBlockInterval, newTime);
                        // 更新的呼叫时间间隔倒计时
                        intervalLiveTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_INTERVAL_LOCK, intervalRedisKey);
                        LOG.info("blockRuleRemind update callBlockInterval time --------->>>>" + intervalLiveTime);
                    }

                    String intervalCountDown = intervalLiveTime == 0L ? "" : DateTimeUtil.getStringEpochSecond(intervalLiveTime, DateTimeUtil.SDFTime);
                    LOG.info("blockRuleRemind callBlockInterval SDFTime --------->>>>" + intervalCountDown);

                    // 隐藏条件，只要时间间隔缓存不死，这个提醒是始终触发的
                    blockRuleRemindVO.setRemindLevel(intervalLevel);
                    blockRuleRemindVO.setCountDown(intervalLiveTime * 1000L);
                }
                // 三十分钟缓存
                String thirtyRedisKey = corpid + "_" + ccId + "_" + "thirty";
                // thirtyLock == 原先设定的三十分钟设定次数(value)
                String thirtyLock = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_THIRTY_LOCK, thirtyRedisKey);
                // 直接修改限制值，之前没有通话设置缓存
                thirtyLock = thirtyLock == null ? "0" : thirtyLock;
                if(StringUtil.isNotEmpty(thirtyLock) && !Objects.equals(callBlockThirtyNum, BasicConstant.ZERO)){
                    Long thirtyLiveTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_THIRTY_LOCK, thirtyRedisKey);
                    Integer thirtyLevel = BasicConstant.TWO;

                    // 修改redis
                    String oldLock = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_OLD_THIRTY_LOCK, thirtyRedisKey);
                    Boolean updateLock = (StringUtil.isNotEmpty(oldLock) && callBlockThirtyNum > StringUtil.toInt(oldLock)) ||
                            (StringUtil.isEmpty(oldLock) && callBlockThirtyNum > StringUtil.toInt(thirtyLock));

                    if(updateLock){
                        // 重新设置规则之后，大于原先设定值时，重置value值，减法
                        // 生命周期三十分钟，value值为自定义次数
                        Integer thirtyNum = callBlockThirtyNum - StringUtil.toInt(thirtyLock);
                        // 生命周期依然是上一个缓存的剩余时间
                        Integer newThirtyTime = thirtyLiveTime.intValue();
                        paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_THIRTY_LOCK, thirtyRedisKey, thirtyNum, newThirtyTime);
                        // 更新的30分钟最多拨打次数倒计时
                        thirtyLiveTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_THIRTY_LOCK, thirtyRedisKey);
                        LOG.info("blockRuleRemind update callBlockThirtyNum time --------->>>>" + thirtyLiveTime);

                        // 冗余缓存之前的拨打次数 lock = 上一次设定的次数
                        paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_OLD_THIRTY_LOCK, thirtyRedisKey, thirtyLock, newThirtyTime);
                        thirtyLiveTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_OLD_THIRTY_LOCK, thirtyRedisKey);
                        LOG.info("blockRuleRemind save old callBlockThirtyNum time --------->>>>" + thirtyLiveTime);

                    }

                    String thirtyCountDown = thirtyLiveTime == 0L ? "" : DateTimeUtil.getStringEpochSecond(thirtyLiveTime, DateTimeUtil.SDFTime);
                    LOG.info("blockRuleRemind callBlockThirtyNum SDFTime --------->>>>" + thirtyCountDown);

                    // 当前剩余的次数或者之前设定的次数
                    thirtyLock = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_THIRTY_LOCK, thirtyRedisKey);
                    thirtyLock = thirtyLock == null ? "0" : thirtyLock;
                    // 查询原子自增的数量
                    String incrThirtyNum = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_THIRTY_INCR_NUM_LOCK, thirtyRedisKey);
                    if(Objects.nonNull(incrThirtyNum)){
                        // 当原子自增的数量开始等于剩余的次数或者之前设定的次数，触发提醒
                        if(StringUtil.toInt(thirtyLock) <= StringUtil.toInt(incrThirtyNum) && callBlockThirtyNum <= StringUtil.toInt(incrThirtyNum)){
                            blockRuleRemindVO.setRemindLevel(thirtyLevel);
                            blockRuleRemindVO.setCountDown(thirtyLiveTime * 1000L);
                        }
                        // 当规则数值改小的时候，判断是否发生触发
                        if(StringUtil.isNotEmpty(oldLock) && callBlockThirtyNum < StringUtil.toInt(oldLock) && callBlockThirtyNum <= StringUtil.toInt(incrThirtyNum)){
                            blockRuleRemindVO.setRemindLevel(thirtyLevel);
                            blockRuleRemindVO.setCountDown(thirtyLiveTime * 1000L);
                        }
                    }
                }

                // 一个自然天缓存
                String dayRedisKey = corpid + "_" + ccId + "_" + "day";
                // dayLock == 原先设定的一个自然天设定次数(value)
                String dayLock = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_DAY_LOCK, dayRedisKey);
                // 直接修改限制值，之前没有通话设置缓存
                dayLock = dayLock == null ? "0" : dayLock;
                if(StringUtil.isNotEmpty(dayLock) && !Objects.equals(callBlockDayNum, BasicConstant.ZERO)){
                    Long dayLiveTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_DAY_LOCK, dayRedisKey);
                    Integer dayLevel = BasicConstant.ONE;

                    // 修改redis
                    String oldLock = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_OLD_DAY_LOCK, dayRedisKey);
                    Boolean updateLock = (StringUtil.isNotEmpty(oldLock) && callBlockDayNum > StringUtil.toInt(oldLock)) ||
                            (StringUtil.isEmpty(oldLock) && callBlockDayNum > StringUtil.toInt(dayLock));

                    Integer now = DateUtil.getInt();
                    Integer redisDayLive = DateUtil.getTodayInt() + RedisConstant.LONG_DURATION - now;
                    LOG.info("blockRuleRemind now dayLock time --------->>>>" + dayLock);
                    if(updateLock){
                        // 重新设置规则之后，大于原先设定值时，重置value值，减法
                        // 生命周期一个自然天，value值为自定义次数
                        Integer dayNum = callBlockDayNum - StringUtil.toInt(dayLock);
                        paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_DAY_LOCK, dayRedisKey, dayNum, redisDayLive);
                        // 更新的一天最多拨打次数倒计时
                        dayLiveTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_DAY_LOCK, dayRedisKey);
                        LOG.info("blockRuleRemind update callBlockDayNum time --------->>>>" + dayLiveTime);

                        // 冗余缓存之前的拨打次数 lock = 上一次设定的次数
                        paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_OLD_DAY_LOCK, dayRedisKey, dayLock, redisDayLive);
                        dayLiveTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_OLD_DAY_LOCK, dayRedisKey);
                        LOG.info("blockRuleRemind save old callBlockDayNum time --------->>>>" + dayLiveTime);

                    }

                    String dayCountDown = dayLiveTime == 0L ? "" : DateTimeUtil.getStringEpochSecond(dayLiveTime, DateTimeUtil.SDFTime);
                    LOG.info("blockRuleRemind callBlockDayNum SDFTime --------->>>>" + dayCountDown);

                    // 当前剩余的次数或者之前设定的次数
                    dayLock = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_DAY_LOCK, dayRedisKey);

                    // 查询原子自增的数量
                    String incrDayNum = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_THIRTY_INCR_NUM_LOCK, thirtyRedisKey);

                    if(Objects.nonNull(incrDayNum)){
                        // 当原子自增的数量开始等于剩余的次数或者之前设定的次数，触发提醒
                        if(StringUtil.toInt(dayLock) <= StringUtil.toInt(incrDayNum) && callBlockDayNum <= StringUtil.toInt(incrDayNum)){
                            blockRuleRemindVO.setRemindLevel(dayLevel);
                            blockRuleRemindVO.setCountDown(dayLiveTime * 1000L);
                        }
                        // 当规则数值改小的时候，判断是否发生触发
                        if(StringUtil.isNotEmpty(oldLock) && callBlockDayNum < StringUtil.toInt(oldLock) && callBlockDayNum <= StringUtil.toInt(incrDayNum)){
                            blockRuleRemindVO.setRemindLevel(dayLevel);
                            blockRuleRemindVO.setCountDown(dayLiveTime * 1000L);
                        }
                    }
                }

                // 用于本地防封号规则调试清理缓存，建议保留代码
                /*paasRedisHelper.removeValue(CallCenterConstant.REDIS_KEY_INTERVAL_LOCK, intervalRedisKey);
                paasRedisHelper.removeValue(CallCenterConstant.REDIS_KEY_THIRTY_LOCK, thirtyRedisKey);
                paasRedisHelper.removeValue(CallCenterConstant.REDIS_KEY_DAY_LOCK, dayRedisKey);
                paasRedisHelper.removeValue(CallCenterConstant.REDIS_KEY_OLD_THIRTY_LOCK, thirtyRedisKey);
                paasRedisHelper.removeValue(CallCenterConstant.REDIS_KEY_OLD_DAY_LOCK, dayRedisKey);
                paasRedisHelper.removeValue(CallCenterConstant.REDIS_KEY_THIRTY_INCR_NUM_LOCK, thirtyRedisKey);
                paasRedisHelper.removeValue(CallCenterConstant.REDIS_KEY_DAY_INCR_NUM_LOCK, dayRedisKey);*/
                if(Objects.nonNull(blockRuleRemindVO.getRemindLevel())){
                    blockRuleRemindVO.setCallBlockTriggerWay(callCenterConfigVO.getCallBlockTriggerWay());
                }
                blockRuleRemindVO.setCallBlockThirtySwitch(callBlockThirtySwitch);
                blockRuleRemindVO.setCallBlockDaySwitch(callBlockDaySwitch);
                blockRuleRemindVO.setCallBlockServer(callBlockServer);
            }
        }
        return new XbbResponse<>(blockRuleRemindVO);
    }

    /**
     * 通话记录列表
     *
     * @param callCallLogListDTO 通话记录列表
     * @return CallMissedCallListVO  通话记录列表回参
     * @throws XbbException
     */
    @Override
    public CallLogListVO callLogList(CallCallLogListDTO callCallLogListDTO) throws XbbException {
        CallLogListVO callLogListVO = new CallLogListVO();
        String userId = callCallLogListDTO.getUserId();
        String corpid = callCallLogListDTO.getCorpid();
        String platform = callCallLogListDTO.getPlatform();
        callCallLogListDTO.initQueryTimeRange();
        // 登录用户
        UserEntity logUser = userModel.getByKey(userId, corpid);
        if (logUser == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.USER_NOT_EXIST);
        }
        // 是否允许使用翻译功能
        boolean isAudioTranslateEnable = false;
        CallCenterAccountUserInfoDTO userInfoDTO = new CallCenterAccountUserInfoDTO();
        BeanUtils.copyProperties(callCallLogListDTO, userInfoDTO);
        CallCenterAccountUserInfoVO userInfoVO = callCenterAccountService.getByXbbUserInfo(userInfoDTO);
        // 判断是否有阿里云呼叫中心权限
        boolean isActiveAliyunCall = callCenterCommonService.isActiveAliyunCall(corpid,userId).IsActiveAliyunAndHasRole();
        if (userInfoVO == null&&!isActiveAliyunCall) {
            return callLogListVO;
        }
        Boolean highPower = userModel.isBoss(logUser);
        boolean accInfo = false;
        if(userInfoVO!=null){
            accInfo = Objects.equals(userInfoVO.getIsAdmin(), 1);
        }

        if (highPower || accInfo) {
            // 老板和话务中心超管能使用翻译功能
            isAudioTranslateEnable = true;
        }
        if (callCallLogListDTO.getDataId() != null) {
            // 指定对象查看通话记录，等于是在客户或联系人详情查看通话记录，不需要话务中心权限
            callCallLogListDTO.setUserId(null);
            //目前详情这边也是需要加上数据权限的过滤的，团队成员改造这次需求加上的，具体加的逻辑请点进方法里面看
            callLogListVO = getAgentCallLogList(callCallLogListDTO, isActiveAliyunCall);
        } else {
            if (highPower) {
                // 老板、管理员等角色不走话务中心的权限判断
                callLogListVO = getAdminCallLogList(callCallLogListDTO);
            } else {
                // 未指定对象类型
                if (Objects.equals(userInfoVO.getIsAdmin(), 1)) {
                    // 超管能看到所有人的通话记录
                    callLogListVO = getAdminCallLogList(callCallLogListDTO);
                } else if (Objects.equals(userInfoVO.getIsSupervisor(), 1)) {
                    // 部门主管能看到全部门的通话记录（包括未接来电）
                    if (callCallLogListDTO.getDepId() != null && callCallLogListDTO.getDepId() > 0L) {
                        if (Objects.equals(callCallLogListDTO.getDepId(), userInfoVO.getDepId())) {
                            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301015);
                        }
                    } else if (callCallLogListDTO.getDepId() == null && callCallLogListDTO.getAgentUserId() == null) {
                        //上面这块的判断不严谨，因为出现数据权限错误的bug，查询发现判断条件除了depId，还有teamId。youli.chen
                        callCallLogListDTO.setTeamId(userInfoVO.getTeamId());
                        //当前端没有传depId时，这个主管权限有问题
                        callCallLogListDTO.setDepId(userInfoVO.getDepId());
                    }
                    callLogListVO = getSupervisorCallLogList(callCallLogListDTO);
                } else if (Objects.equals(userInfoVO.getIsAgent(), 1)) {
                    // 坐席能看到自己的通话记录（包括未接来电）
                    callLogListVO = getAgentCallLogList(callCallLogListDTO, isActiveAliyunCall);
                } else {
                    // 对于非呼叫中心用户，直接过滤
                    return callLogListVO;
                }
            }
        }
        // 度言和销帮帮呼叫中心数据处理
        checkCallMsg(callCallLogListDTO, callLogListVO, corpid, userId, isAudioTranslateEnable);
        if (callCallLogListDTO.getType() != null && callCallLogListDTO.getResult() != null) {
            if (callCallLogListDTO.getType().equals(0) && callCallLogListDTO.getResult().equals(0)) {
                //销帮帮呼叫中心未接来电计数清零
                paasRedisHelper.setValue(CallCenterConstant.CUSTOMER_MISS_CALLLOG_SUM, corpid + "_" + userId,
                        0, null);
            }
        }
        return callLogListVO;
    }

    /**
     * 查找度言未接来电通话记录
     *
     * @param callCallLogListDTO 查找度言未接来电通话记录
     * @return CallMissedCallListVO  查找度言未接来电通话记录回参
     * @throws XbbException
     */
    @Override
    public XbbResponse<CallLogListVO> orgMissedCallList(CallCallLogListDTO callCallLogListDTO) throws XbbException {
        CallLogListVO callLogListVO;
        CallCenterAccountUserInfoDTO userInfoDTO = new CallCenterAccountUserInfoDTO();
        BeanUtils.copyProperties(callCallLogListDTO, userInfoDTO);
        CallCenterAccountUserInfoVO userInfoVO = callCenterAccountService.getByXbbUserInfo(userInfoDTO);
        if (userInfoVO == null) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301003);
        } else if (Objects.equals(userInfoVO.getIsAdmin(), 1)) {
            // 超管能看到所有人的通话记录
            callLogListVO = getAdminMissedCallLogList(callCallLogListDTO);
        } else if (userInfoVO.getIsSupervisor() == 1) {
            // 部门主管能看到全部门的通话记录（包括未接来电）
            if (callCallLogListDTO.getDepId() != null && callCallLogListDTO.getDepId() > 0L) {
                if (Objects.equals(callCallLogListDTO.getDepId(), userInfoVO.getDepId())) {
                    throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301015);
                }
                callCallLogListDTO.setDepId(userInfoVO.getDepId());
            }
            callLogListVO = getSupervisorMissedCallLogList(callCallLogListDTO);
        } else {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301002);
        }
        if (callLogListVO.getCallLogList().size() > 0) {
            initCallLogInfo4Show(callCallLogListDTO.getCorpid(), callLogListVO.getCallLogList());
        }
        return new XbbResponse<>(callLogListVO);
    }

    /**
     * 获取通话记录的录音（直接拼接度言通话录音文件的路径，格式.oga）
     *
     * @param callRecordStaticDTO 获取通话记录的录音（直接拼接度言通话录音文件的路径，格式.oga）入参
     * @return CallLogRecordStaticVO  获取通话记录的录音（直接拼接度言通话录音文件的路径，格式.oga）回参
     * @throws XbbException
     */
    @Override
    public XbbResponse<CallLogRecordStaticVO> callLogRecordStatic(CallRecordStaticDTO callRecordStaticDTO) throws XbbException {
        CallLogRecordStaticVO callLogRecordStaticVO = new CallLogRecordStaticVO();
        // 话务中心平台，参考CallCenterTypeEnum
        Integer moduleType = callRecordStaticDTO.getModuleType();
        // 公司ID
        String corpid = callRecordStaticDTO.getCorpid();

        if (callCenterCommonService.notCallCenterModule(moduleType)) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301029);
        }
        if(Objects.equals(moduleType, CallCenterTypeEnum.CALL_CENTER_XBB.getCode())){
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301054);
        }
        if (callCenterCommonService.isWrongMobilePhoneNum(callRecordStaticDTO.getAnotherPhoneNum())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100027);
        }
        CallCenterCallLogEntity callCenterCallLogEntity = callCenterCallLogModel.getByKey(callRecordStaticDTO.getCallLogId(),
                callRecordStaticDTO.getCorpid());
        String url;
        if (callCenterCallLogEntity == null) {
            // 通话记录录音不存在
            // 客户号码
            String anotherPhoneNum = callRecordStaticDTO.getAnotherPhoneNum();
            // 通话时间
            Integer callTime = callRecordStaticDTO.getCallTime();
            url = getCallLogRecordUrlStatic(corpid, moduleType, anotherPhoneNum, callTime, null);
        } else if (callCenterCallLogEntity.getCallUuid() == null) {
            // 客户号码
            String anotherPhoneNum = callCenterCallLogEntity.getAnotherPhoneNum();
            if (StringUtil.isEmpty(anotherPhoneNum)) {
                anotherPhoneNum = callRecordStaticDTO.getAnotherPhoneNum();
            }
            // 通话时间
            Integer callTime = callCenterCallLogEntity.getCallTime();
            if (callTime == null) {
                callTime = callRecordStaticDTO.getCallTime();
            }
            url = getCallLogRecordUrlStatic(corpid, moduleType, anotherPhoneNum, callTime, callCenterCallLogEntity);
        } else if (StringUtil.isEmpty(callCenterCallLogEntity.getRecordUrl())) {
            url = getCallLogRecordUrlByUuidStatic(corpid, moduleType, callCenterCallLogEntity);
        } else {
            // 通话标识已经存在或录音文件路径已经存在
            url = callCenterCallLogEntity.getRecordUrl();
        }
        callLogRecordStaticVO.setUrl(url);
        return new XbbResponse<>(callLogRecordStaticVO);
    }

    /**
     * 获取通话记录的录音（通过度言API获取文件路径，最后得到.oga的路径）
     *
     * @param callRecordDynamicDTO 获取通话记录的录音（通过度言API获取文件路径，最后得到.oga的路径）入参
     * @return CallLogRecordStaticVO  获取通话记录的录音（通过度言API获取文件路径，最后得到.oga的路径）回参
     * @throws XbbException
     */
    @Override
    public XbbResponse<CallLogRecordStaticVO> callLogRecordDynamic(CallRecordDynamicDTO callRecordDynamicDTO) throws XbbException {
        CallLogRecordStaticVO callLogRecordStaticVO = new CallLogRecordStaticVO();
        // 话务中心平台，参考CallCenterTypeEnum
        Integer moduleType = callRecordDynamicDTO.getModuleType();
        // 公司ID
        String corpid = callRecordDynamicDTO.getCorpid();

        if (callCenterCommonService.notCallCenterModule(moduleType)) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301029);
        }
        if (callCenterCommonService.isWrongMobilePhoneNum(callRecordDynamicDTO.getAnotherPhoneNum())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100027);
        }
        CallCenterCallLogEntity callCenterCallLogEntity = callCenterCallLogModel.getByKey(callRecordDynamicDTO.getCallLogId(),
                callRecordDynamicDTO.getCorpid());
        String url;
        if (callCenterCallLogEntity == null) {
            // 通话记录录音不存在
            // 客户号码
            String anotherPhoneNum = callRecordDynamicDTO.getAnotherPhoneNum();
            // 通话时间
            Integer callTime = callRecordDynamicDTO.getCallTime();
            url = getCallLogRecordUrlDynamic(corpid, moduleType, anotherPhoneNum, callTime, null);
        } else if (callCenterCallLogEntity.getCallUuid() == null) {
            // 客户号码
            String anotherPhoneNum = callCenterCallLogEntity.getAnotherPhoneNum();
            if (StringUtil.isEmpty(anotherPhoneNum)) {
                anotherPhoneNum = callRecordDynamicDTO.getAnotherPhoneNum();
            }
            // 通话时间
            Integer callTime = callCenterCallLogEntity.getCallTime();
            if (callTime == null) {
                callTime = callRecordDynamicDTO.getCallTime();
            }
            url = getCallLogRecordUrlDynamic(corpid, moduleType, anotherPhoneNum, callTime, callCenterCallLogEntity);
        } else if (StringUtil.isEmpty(callCenterCallLogEntity.getRecordUrl())) {
            url = getCallLogRecordUrlByUuidDynamic(corpid, moduleType, callCenterCallLogEntity);
        } else {
            // 通话标识已经存在或录音文件路径已经存在
            url = callCenterCallLogEntity.getRecordUrl();
        }
        callLogRecordStaticVO.setUrl(url);
        return new XbbResponse<>(callLogRecordStaticVO);
    }

    /**
     * 通话记录数据封装
     *
     * @param saveEntity         通话记录Entity
     * @param callCallLogSaveDTO 保存通话记录入参
     * @return
     */
    private void duYanCallLog(CallCenterCallLogEntity saveEntity, CallCallLogSaveDTO callCallLogSaveDTO) throws XbbException{
        String corpid = callCallLogSaveDTO.getCorpid();
        String userId = callCallLogSaveDTO.getUserId();
        Integer moduleType = callCallLogSaveDTO.getModuleType();
        String apiKey = null;
        if(Objects.equals(moduleType, CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode())){
            apiKey = callCenterOrganizationService.getApiKey(corpid, moduleType);
        }

        // 响铃时间
        Integer ringTime;
        // 通话时间
        Integer durationTime;

        //只有度言呼叫中心的数据需要同步和录音处理,逍邦呼叫中心跳过 youli.chen
        if(Objects.equals(moduleType, CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode())){
            if (callCallLogSaveDTO.getConnectTime() == null || callCallLogSaveDTO.getConnectTime() == 0) {
                // 未接通的呼叫
                ringTime = callCallLogSaveDTO.getEndTime() - callCallLogSaveDTO.getStartTime();
                durationTime = 0;
                // 通话结果：失败
                callCallLogSaveDTO.setResult(CallLogResultEnum.FAIL.getCode());
            } else {
                // 接通的呼叫
                ringTime = callCallLogSaveDTO.getConnectTime() - callCallLogSaveDTO.getStartTime();
                durationTime = callCallLogSaveDTO.getEndTime() - callCallLogSaveDTO.getConnectTime();
                // 通话结果：成功
                callCallLogSaveDTO.setResult(CallLogResultEnum.SUCCESS.getCode());
            }
            //解释：去度言查询通话记录
            CallCenterCallLogEntity formatOriginCallLogEntity = callCenterCommonService.getOriginCallLogDetail(apiKey, moduleType, callCallLogSaveDTO.getUuid());

            //解释：同步度言通话记录
            if (formatOriginCallLogEntity == null) {
                if (callCallLogSaveDTO.getStartTime() != null && StringUtil.isNotEmpty(callCallLogSaveDTO.getAnotherPhoneNum())) {
                    formatOriginCallLogEntity = getOriginCallLogDetailByList(corpid, null,
                            moduleType, callCallLogSaveDTO.getStartTime(), callCallLogSaveDTO.getAnotherPhoneNum(), callCallLogSaveDTO.getResult());
                }
                if (formatOriginCallLogEntity == null) {
                    BeanUtils.copyProperties(callCallLogSaveDTO, saveEntity);
                    saveEntity.setCallTime(callCallLogSaveDTO.getStartTime());
                    saveEntity.setDuration(durationTime);
                    saveEntity.setRingTime(ringTime);
                } else {
                    BeanUtils.copyProperties(formatOriginCallLogEntity, saveEntity);
                }
            } else {
                BeanUtils.copyProperties(formatOriginCallLogEntity, saveEntity);
                saveEntity.setCorpid(corpid);
            }
        }else if(Objects.equals(moduleType, CallCenterTypeEnum.CALL_CENTER_XBB.getCode())){
            saveEntity = callCenterCommonService.packageXbbCallLogEntity(saveEntity, callCallLogSaveDTO);
        }
        saveEntity.setUserId(userId);
    }

    /**
     * 度言和销帮帮呼叫中心数据处理
     *
     * @param callCallLogListDTO     通话记录列表入参
     * @param callLogListVO          通话记录列表回参
     * @param corpid                 公司ID
     * @param userId                 用户ID
     * @param isAudioTranslateEnable 是否允许使用翻译功能
     * @return callLogListVO 通话记录列表回参
     * @throws XbbException
     */
    private CallLogListVO checkCallMsg(CallCallLogListDTO callCallLogListDTO, CallLogListVO callLogListVO, String corpid,
                                       String userId, boolean isAudioTranslateEnable) throws XbbException {
        List<CallLogPojo> callLogList = callLogListVO.getCallLogList();
        if(callLogList != null){
            // 只有度言的通话记录需要同步，销帮帮呼叫中心跳过
            if (callCallLogListDTO.getModuleType().equals(CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode())) {
                List<CallCenterCallLogEntity> callLogs = new ArrayList<>();
                try {
                    BeanUtil.copyPropertiesList(callLogList, callLogs, CallCenterCallLogEntity.class);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                syncCallLog(corpid, callCallLogListDTO.getModuleType(), callLogs);
            } else if (callCallLogListDTO.getModuleType().equals(CallCenterTypeEnum.CALL_CENTER_XBB.getCode())) {
                //销帮帮呼叫中心过期录音文件提示
                CallCenterOrgGetByCorpIdVO orgUrl = callCenterOrganizationService.getByCorpId(corpid,
                        callCallLogListDTO.getModuleType());
                if(orgUrl!=null&&Objects.nonNull(orgUrl.getUsefulTime())){
                    for (CallLogPojo callLog : callLogList) {
                        Date date = new Date();
                        Date lastDay;
                        Calendar calendar = new GregorianCalendar();
                        Date addTime = DateUtil.getDate(callLog.getAddTime());
                        calendar.setTime(addTime);
                        calendar.add(Calendar.YEAR, orgUrl.getUsefulTime());
                        lastDay = calendar.getTime();
                        if (lastDay.getTime() - date.getTime() < 0) {
                            callLog.setRecordUrl(I18nMessageUtil.getMessage(I18nStringConstant.EXCEEDED_MAXIMUM_STORAGE_PERIOD));
                        }
                    }
                }
            }

            initCallLogInfo4Show(corpid, callLogList);
            //封装客户模板设置的号码是否可见属性 youli.chen
            initCallLogListPhone(callCallLogListDTO, corpid, callLogList);

            // 当前公司是否允许使用翻译功能  翻译功能也是区分度言和销帮帮的 youli.chen
            boolean isOrgAudioTranslateActived = callCenterOrganizationService.isAudioTranslate(corpid,
                    callCallLogListDTO.getModuleType(), userId);
            callLogListVO.setIsAudioTranslateEnable(isAudioTranslateEnable && isOrgAudioTranslateActived);
        }
        return callLogListVO;
    }

    /**
     * 通话记录防骚扰，以及同步跟进记录,防封号规则
     *
     * @param saveResult
     * @param callCallLogSaveVO
     * @param callCallLogSaveDTO
     * @param callCenterConfigVO
     * @return
     * @throws XbbException
     */
    private CallCallLogSaveVO communicateAndCallNumPer(CallCenterCallLogEntity saveEntity, Integer saveResult,
                                                       CallCallLogSaveVO callCallLogSaveVO,
                                                       CallCallLogSaveDTO callCallLogSaveDTO,
                                                       CallCenterConfigVO callCenterConfigVO, String customerId) throws XbbException {
        String corpid = callCallLogSaveDTO.getCorpid();
        String userId = callCallLogSaveDTO.getUserId();

        if (saveResult > 0) {
            if (callCallLogSaveDTO.getModuleType() == CallCenterTypeEnum.CALL_CENTER_XBB.getCode()) {
                // 防骚扰次数+1
                Integer now = DateUtil.getInt();
                String sdfDate = DateUtil.SDFDate.format(Calendar.getInstance().getTime());
                if (callCenterConfigVO.getIsAntiDisturb().equals(1) && !Objects.equals(callCallLogSaveDTO.getRefType(), CallCenterTypeEnum.UNKNOWN.getCode())) {
                    if (!callCenterConfigVO.getCallNumPerDay().equals(0)) {
                        paasRedisHelper.getIncrNum(CallCenterConstant.CUSTOMER_DISTURB_DAY, corpid + "_" + customerId,
                                DateUtil.getTodayInt() + 86400 - now, 1, 1);
                    }
                    if (!callCenterConfigVO.getCallNumPerWeek().equals(0)) {
                        //剩余时间=当前自然周最后一天的24时24分24秒-当前时间
                        paasRedisHelper.getIncrNum(CallCenterConstant.CUSTOMER_DISTURB_WEEK, corpid + "_" + customerId,
                                DateUtil.getWeekLastDayInSomeday(DateUtil.getInt(sdfDate, DateUtil.SDFDate)) - now, 1, 1);
                    }
                    if (!callCenterConfigVO.getCallNumPerMonth().equals(0)) {
                        //剩余时间=当前自然月最后一天的24时24分24秒-当前时间
                        paasRedisHelper.getIncrNum(CallCenterConstant.CUSTOMER_DISTURB_MONTH, corpid + "_" + customerId,
                                DateUtil.getLastDateOfThisMonth() - now, 1, 1);
                    }
                }

                // 未接来电计数
                Long incrNumber = 0L;
                if (saveEntity.getType().equals(0) && saveEntity.getResult().equals(0)) {
                    incrNumber = paasRedisHelper.getIncrNum(CallCenterConstant.CUSTOMER_MISS_CALLLOG_SUM,
                            corpid + "_" + userId, 0, 1, 1);
                }
                callCallLogSaveVO.setMissCallLogSum(incrNumber);

                // 防封号规则
                // 针对呼出通话以及开启防封号规则，并ccid不为空(防止误统计)
                if(Objects.equals(saveEntity.getType(), BasicConstant.ONE) && Objects.equals(callCenterConfigVO.getCallBlockRule(), BasicConstant.ONE)
                        && StringUtil.isNotEmpty(callCallLogSaveDTO.getCcId())){
                    callBlockRule(callCallLogSaveDTO, callCenterConfigVO);
                }
            }

            Long refId = callCallLogSaveDTO.getRefId() == null ? 0L : callCallLogSaveDTO.getRefId();
            if (refId > 0L) {
                // 存在通话对象
                AutoCommunicateDTO autoCommunicateDTO = new AutoCommunicateDTO();
                autoCommunicateDTO.setCorpid(corpid);
                autoCommunicateDTO.setUserId(userId);
                autoCommunicateDTO.setPlatform(callCallLogSaveDTO.getPlatform());
                autoCommunicateDTO.setDuration(saveEntity.getDuration());
                autoCommunicateDTO.setResult(saveEntity.getResult());
                autoCommunicateDTO.setModuleType(callCallLogSaveDTO.getModuleType());
                autoCommunicateDTO.setCallLogTypeEnum(CallLogTypeEnum.getByCode(callCallLogSaveDTO.getType()));
                autoCommunicateDTO.setRefId(callCallLogSaveDTO.getRefId());
                autoCommunicateDTO.setRefType(callCallLogSaveDTO.getRefType());
                autoCommunicateDTO.setAnotherPhoneNum(callCallLogSaveDTO.getAnotherPhoneNum());
                autoCommunicateDTO.setStartTime(callCallLogSaveDTO.getStartTime());
                autoCommunicateDTO.setType(callCallLogSaveDTO.getType());
                callCenterCommonService.autoCommunicate(autoCommunicateDTO);
            }
        } else {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301055);
        }
        return callCallLogSaveVO;
    }

    /**
     * 坐席查找：根据业务对象封装的条件查找符合的列表
     *
     * @param callCallLogListDTO 业务对象封装的条件
     * @param isActiveAliyunCall 是否有云呼的权限
     * @return CallLogListVO 符合条件的话务中心通话记录列表
     * @throws XbbException 业务异常
     * @author youli.chen
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public CallLogListVO getAgentCallLogList(CallCallLogListDTO callCallLogListDTO, boolean isActiveAliyunCall) throws XbbException {
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        //能到这一步的肯定是老呼叫中心的通话记录列表，因为详情页的通话记录列表在上面一层已经把userId置为null
        if (Objects.nonNull(callCallLogListDTO.getUserId())) {
            boolQueryBuilder.filter(termQuery("userId.keyword", callCallLogListDTO.getUserId()));
        }else {
            detailTabDataPermissionHelp.detailTabCallLogDataFilter(boolQueryBuilder, callCallLogListDTO, isActiveAliyunCall);
        }
        return getCallLogList(boolQueryBuilder, callCallLogListDTO);
    }

    /**
     * 团队主管查找：根据业务对象封装的条件查找符合的列表
     *
     * @param callCallLogListDTO 业务对象封装的条件
     * @return CallLogListVO 符合条件的话务中心通话记录列表
     * @throws XbbException 业务异常
     * @author youli.chen
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public CallLogListVO getSupervisorCallLogList(CallCallLogListDTO callCallLogListDTO) throws XbbException {
        CallLogListVO callLogListVO = new CallLogListVO();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        if(Objects.nonNull(callCallLogListDTO.getDepId())){
            // 输入当前主管的部门id查询部门下的所有员工
            List<Long> depIdIn = new ArrayList<>();
            depIdIn.add(callCallLogListDTO.getDepId());
            List<String> userIdIn = userModel.getUserIdsRecursionDep(depIdIn, callCallLogListDTO.getCorpid(), 1);
            if (userIdIn != null && userIdIn.size() > 0) {
                boolQueryBuilder.filter(termsQuery("userId", userIdIn));
            } else {
                // 部门查询不到人，说明该登录人不在该部门，直接返回空列表
                return callLogListVO;
            }
        }else{
            String agentUserId = callCallLogListDTO.getAgentUserId();
            List<String> userIdIn = new ArrayList<>();

            if(Objects.nonNull(agentUserId)){
                userIdIn.add(agentUserId);
                boolQueryBuilder.filter(termsQuery("userId", userIdIn));
            }
        }
        return getCallLogList(boolQueryBuilder, callCallLogListDTO);
    }

    /**
     * 超管查找：根据业务对象封装的条件查找符合的列表
     *
     * @param callCallLogListDTO 业务对象封装的条件
     * @return CallLogListVO 符合条件的话务中心通话记录列表
     * @throws XbbException 业务异常
     * @author youli.chen
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public CallLogListVO getAdminCallLogList(CallCallLogListDTO callCallLogListDTO) throws XbbException {
        CallLogListVO callLogListVO = new CallLogListVO();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        if (callCallLogListDTO.getDepId() != null && callCallLogListDTO.getDepId() > 0L) {
            List<Long> depIdIn = new ArrayList<>();
            depIdIn.add(callCallLogListDTO.getDepId());
            List<String> userIdIn = userModel.getUserIdsRecursionDep(depIdIn, callCallLogListDTO.getCorpid(), 1);
            if (userIdIn != null && userIdIn.size() > 0) {
                boolQueryBuilder.filter(termsQuery("userId.keyword", userIdIn));
            } else {
                // 部门查询不到人，说明该登录人不在该部门，直接返回空列表
                return callLogListVO;
            }
        } else if (Objects.nonNull(callCallLogListDTO.getAgentUserId())){
            boolQueryBuilder.filter(termQuery("userId.keyword", callCallLogListDTO.getAgentUserId()));
        }
        return getCallLogList(boolQueryBuilder,  callCallLogListDTO);
    }

    /**
     * 封装通话记录的更多详情（以及添加已经被转为客户的通话记录）
     *
     * @param corpid      公司id
     * @param callLogList 通话记录列表
     * @throws XbbException 业务异常
     * @author youli.chen
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public void initCallLogInfo4Show(String corpid, List<CallLogPojo> callLogList) throws XbbException {
        // 封装前端显示的时间格式
        for (CallLogPojo it : callLogList) {
            String time = "";
            if (Objects.equals(CallCenterCallLogCallSourceEnum.CALL_CENTER.getCode(), it.getCallSource())) {
                it.setCallTimeShow(DateUtil.getString(it.getCallTime(), DateUtil.SDF));
            } else {
                it.setCallTimeShow(DateUtil.getString(it.getAddTime(), DateUtil.SDF));
            }
        }
        // 封装前端显示的坐席名称
        initCallLogListUserName(corpid, callLogList);
        // 封装已经被转为客户的陌生号码的客户名称
        List<CallCenterCallLogEntity> callLogs = new ArrayList<>();
        try {
            BeanUtil.copyPropertiesList(callLogList, callLogs, CallCenterCallLogEntity.class);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        initCallLogListRefName(corpid, callLogs);
    }

    /**
     * 封装通话记录的坐席名称
     *
     * @param corpid      公司Id
     * @param callLogList 通话记录列表
     * @throws XbbException 业务异常
     * @author youli.chen
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public void initCallLogListUserName(String corpid, List<CallLogPojo> callLogList) throws XbbException {
        Set<String> userIdSet = new HashSet<>();
        for (CallLogPojo it : callLogList) {
            userIdSet.add(it.getUserId());
        }
        List<String> userIds = new ArrayList<>(userIdSet);
        Map<String, String> userIdNameMap = userModel.getUserIdNameMap(corpid, userIds);
        for (CallLogPojo it : callLogList) {
            if(StringUtil.isEmpty(it.getUsername())){
                it.setUsername(userIdNameMap.get(it.getUserId()));
            }
        }
    }

    /**
     * 封装已经被转为客户的陌生号码的客户名称
     *
     * @param corpid      公司Id
     * @param callLogList 通话记录列表
     * @throws XbbException 业务异常
     * @author youli.chen
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public void initCallLogListRefName(final String corpid, List<CallCenterCallLogEntity> callLogList) throws XbbException {
        for (CallCenterCallLogEntity it : callLogList) {
            // TODO 2017-11-24 章华隽 当前for循环查询效率较低，考虑查询封装进map再插入数据，最后统一更新
            if (Objects.equals(XbbRefTypeEnum.UNKNOWN.getCode(), it.getRefType())) {
                final CallCenterFindRefDTO refDTO = callCenterCommonService.findRefByPhoneNum(corpid, it.getAnotherPhoneNum());
                if (refDTO.getRefId() != null && refDTO.getRefId() > 0) {
                    it.setRefId(refDTO.getRefId());
                    it.setRefType(refDTO.getRefType());
                    it.setRefName(refDTO.getRefName());
                    final Long logId = it.getId();
                    ThreadPoolHelper.getInstance().submitExecutorRunnable(callCenterThreadPool, new Runnable() {
                        @Override
                        public void run() {
                            CallCenterCallLogEntity callLogEntity = callCenterCallLogModel.getByKey(logId, corpid);
                            callLogEntity.setRefId(refDTO.getRefId());
                            callLogEntity.setRefType(refDTO.getRefType());
                            callLogEntity.setRefName(refDTO.getRefName());
                            try {
                                callCenterCallLogModel.update(callLogEntity);
                            } catch (XbbException e) {
                                e.printStackTrace();
                                LOG.error("通话记录保存失败", e);
                            }
                        }
                    });
                }
            }
        }
    }

    /**
     * 封装客户模板设置的号码是否可见属性
     *
     * @param corpid      公司Id
     * @param callLogList 通话记录列表
     * @throws XbbException 业务异常
     * @author youli.chen
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public void initCallLogListPhone(CallCallLogListDTO callCallLogListDTO, String corpid, List<CallLogPojo> callLogList) throws XbbException {
        HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
        BeanUtil.copyProperties(callCallLogListDTO, handlerExplainDTO);
        List<Long> customerIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Long> contactIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Long> clueIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        callLogList.forEach(callLogPojo -> {
            if (Objects.equals(callLogPojo.getRefType(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())) {
                customerIdList.add(callLogPojo.getRefId());
            }
            if (Objects.equals(callLogPojo.getRefType(), XbbRefTypeEnum.CONTACT.getCode())) {
                contactIdList.add(callLogPojo.getRefId());
            }
            if (Objects.equals(callLogPojo.getRefType(), XbbRefTypeEnum.CLUE.getCode())) {
                clueIdList.add(callLogPojo.getRefId());
            }
        });
        // 客户
        BoolQueryBuilder customerBuilder = boolQuery();
        customerBuilder.filter(termQuery("corpid.keyword",corpid));
        customerBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        customerBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(),customerIdList));
        // 限制返回值
        List<String> field = Arrays.asList(FieldTypeEnum.DATAID.getAlias(), StringConstant.JSON_DATA, ParameterConstant.FORMID);


        IndexTypeEnum indexTypeEnum = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());

        List<PaasFormDataEntity> customerESList = esHelper.findByScroll(indexTypeEnum,customerBuilder,PaasFormDataEntity.class, field);

        List<Long> customerFormList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, Boolean> customerFormMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        customerESList.forEach(item -> customerFormList.add(item.getFormId()));
        for(Long formId : customerFormList){
            PaasFormExplainEntity formExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
            if(formExplainEntity == null){
                continue;
            }
            List<FieldAttrEntity> explainList = JSONArray.parseArray(formExplainEntity.getExplains(), FieldAttrEntity.class);
            Map<String, FieldAttrEntity> explainMap = new HashMap<>(explainList.size());
            explainList.forEach((item) -> explainMap.put(item.getAttr(), item));
            boolean phoneCansee = commonHelp.attrCanSee(CustomerManagementEnum.PHONE.getAttr(), explainMap, handlerExplainDTO);
            if(phoneCansee){
                List<? extends FieldAttrEntity> explainSubFormList =  explainMap.get(CustomerManagementEnum.PHONE.getAttr()).getSubForm().getItems();
                Map<String, FieldAttrEntity> explainSubFormMap = new HashMap<>(explainSubFormList.size());
                explainSubFormList.forEach((item) -> explainSubFormMap.put(item.getAttr(), item));
                boolean text2CanSee = commonHelp.attrCanSee(StringConstant.PHONE_TEL_ATTR, explainSubFormMap, handlerExplainDTO);
                if(!text2CanSee){
                    phoneCansee = false;
                }
            }
            customerFormMap.put(formId, phoneCansee);
        }

        Map<Long, Boolean> customerPhone = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        customerESList.forEach(customer -> {
            if(customerFormMap.containsKey(customer.getFormId())){
                customerPhone.put(customer.getDataId(), customerFormMap.get(customer.getFormId()));
            }
        });

        // 联系人
        BoolQueryBuilder contactBuilder = boolQuery();
        //解析查询条件
        contactBuilder.filter(termQuery("corpid.keyword", callCallLogListDTO.getCorpid()));
        contactBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        contactBuilder.filter(termsQuery("dataId",contactIdList));
        // 限制返回值
        List<String> fieldList = Arrays.asList(FieldTypeEnum.DATAID.getAlias(), StringConstant.JSON_DATA, ParameterConstant.FORMID);
        List<PaasFormDataEntityExt> contactESList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CONTACT,contactBuilder,PaasFormDataEntityExt.class,fieldList);

        List<Long> contactFormList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, Boolean> contactFormMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        contactESList.forEach(item -> contactFormList.add(item.getFormId()));
        for(Long formId : contactFormList){
            PaasFormExplainEntity formExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
            if(formExplainEntity == null){
                continue;
            }
            List<FieldAttrEntity> explainList = JSONArray.parseArray(formExplainEntity.getExplains(), FieldAttrEntity.class);
            Map<String, FieldAttrEntity> explainMap = new HashMap<>(explainList.size());
            explainList.forEach((item) -> explainMap.put(item.getAttr(), item));
            boolean phoneCansee = commonHelp.attrCanSee(ContactEnum.PHONE.getAttr(), explainMap, handlerExplainDTO);
            if(phoneCansee){
                List<? extends FieldAttrEntity> explainSubFormList = explainMap.get(ContactEnum.PHONE.getAttr()).getSubForm().getItems();
                Map<String, FieldAttrEntity> explainSubFormMap = new HashMap<>(explainSubFormList.size());
                explainSubFormList.forEach((item) -> explainSubFormMap.put(item.getAttr(), item));
                boolean text2CanSee = commonHelp.attrCanSee(StringConstant.PHONE_TEL_ATTR, explainSubFormMap, handlerExplainDTO);
                if(!text2CanSee){
                    phoneCansee = false;
                }
            }
            contactFormMap.put(formId, phoneCansee);
        }

        Map<Long, Boolean> contactPhone = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        contactESList.forEach(contact -> {
            if(contactFormMap.containsKey(contact.getFormId())){
                contactPhone.put(contact.getDataId(), contactFormMap.get(contact.getFormId()));
            }
        });

        // 线索
        BoolQueryBuilder clueBuilder = boolQuery();
        clueBuilder.filter(termQuery("corpid.keyword",corpid));
        clueBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        clueBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(),clueIdList));
        // 限制返回值
        List<String> clueField = Arrays.asList(FieldTypeEnum.DATAID.getAlias(), StringConstant.JSON_DATA, ParameterConstant.FORMID);
        List<PaasFormDataEntity> clueESList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CLUE,clueBuilder,PaasFormDataEntity.class, clueField);

        List<Long> clueFormList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, Boolean> clueFormMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        clueESList.forEach(item -> clueFormList.add(item.getFormId()));
        for(Long formId : clueFormList){
            PaasFormExplainEntity formExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
            if(formExplainEntity == null){
                continue;
            }
            List<FieldAttrEntity> explainList = JSONArray.parseArray(formExplainEntity.getExplains(), FieldAttrEntity.class);
            Map<String, FieldAttrEntity> explainMap = new HashMap<>(explainList.size());
            explainList.forEach((item) -> explainMap.put(item.getAttr(), item));
            boolean phoneCansee = commonHelp.attrCanSee(ClueEnum.PHONE.getAttr(), explainMap, handlerExplainDTO);
            if(phoneCansee){
                List<? extends FieldAttrEntity> explainSubFormList =  explainMap.get(ClueEnum.PHONE.getAttr()).getSubForm().getItems();
                Map<String, FieldAttrEntity> explainSubFormMap = new HashMap<>(explainSubFormList.size());
                explainSubFormList.forEach((item) -> explainSubFormMap.put(item.getAttr(), item));
                boolean text2CanSee = commonHelp.attrCanSee(StringConstant.PHONE_TEL_ATTR, explainSubFormMap, handlerExplainDTO);
                if(!text2CanSee){
                    phoneCansee = false;
                }
            }
            clueFormMap.put(formId, phoneCansee);
        }

        Map<Long, Boolean> cluePhone = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        clueESList.forEach(clue -> {
            if(clueFormMap.containsKey(clue.getFormId())){
                cluePhone.put(clue.getDataId(), clueFormMap.get(clue.getFormId()));
            }
        });

        for (CallLogPojo callLogPojo : callLogList) {
            // 电话可见判断
            boolean attrVisible = true;
            if (Objects.equals(callLogPojo.getRefType(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())) {
                if (customerPhone.containsKey(callLogPojo.getRefId())) {
                    attrVisible = customerPhone.get(callLogPojo.getRefId());
                }
            }
            if (Objects.equals(callLogPojo.getRefType(), XbbRefTypeEnum.CONTACT.getCode())) {
                if (contactPhone.containsKey(callLogPojo.getRefId())) {
                    attrVisible = contactPhone.get(callLogPojo.getRefId());
                }
            }
            if (Objects.equals(callLogPojo.getRefType(), XbbRefTypeEnum.CLUE.getCode())) {
                if (cluePhone.containsKey(callLogPojo.getRefId())) {
                    attrVisible = cluePhone.get(callLogPojo.getRefId());
                }
            }
            callLogPojo.setHiddenPhoneNum(callLogPojo.getAnotherPhoneNum());
            if (!attrVisible) {
                //陌生号码不是客户，没有进入业务模板管理，不隐藏
                if (callLogPojo.getAnotherPhoneNum() != null && callLogPojo.getRefName() != null) {
                    if (!callLogPojo.getRefName().contains(I18nMessageUtil.getMessage(I18nStringConstant.STRANGE_NUMBER))) {
                        String telNum;
                        if (callLogPojo.getAnotherPhoneNum().length() > 5) {
                            telNum = callLogPojo.getAnotherPhoneNum().substring(0, 3) + "****" +
                                    callLogPojo.getAnotherPhoneNum().substring(callLogPojo.getAnotherPhoneNum().length() - 2,
                                            callLogPojo.getAnotherPhoneNum().length());
                        } else {
                            telNum = "*****";
                        }
                        callLogPojo.setHiddenPhoneNum(telNum);
                    }
                }
            }
        }
    }

    /**
     * 管理员获取未接来电
     *
     * @param callCallLogListDTO 通话记录请求参数
     * @return CallLogListVO 封装的通话记录返回参数
     * @throws XbbException 业务异常
     * @author youli.chen
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public CallLogListVO getAdminMissedCallLogList(CallCallLogListDTO callCallLogListDTO) throws XbbException {
        return getOrgMissedCallLogList(callCallLogListDTO, callCallLogListDTO.getDepId());
    }

    /**
     * 团队主管获取未接来电
     *
     * @param callCallLogListDTO 通话记录请求参数
     * @return CallCenterCallLogResponseParamPojo 封装的通话记录返回参数
     * @throws XbbException 业务异常
     * @author youli.chen
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public CallLogListVO getSupervisorMissedCallLogList(CallCallLogListDTO callCallLogListDTO) throws XbbException {
        if (callCallLogListDTO.getDepId() == null) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301056);
        }
        return getOrgMissedCallLogList(callCallLogListDTO, callCallLogListDTO.getDepId());
    }

    /**
     * 通过远程通话记录列表获取通话记录详情
     *
     * @param corpid     公司id
     * @param id         通话记录ID
     * @param moduleType 第三方话务平台，参考AppStoreTypeEnum
     * @param callTime   通话开始时间
     * @param target     目标用户号码
     * @param result     通话结果
     * @return CallCenterCallLogEntity 封装好的通话记录
     * @throws XbbException 业务异常
     * @author youli.chen
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public CallCenterCallLogEntity getOriginCallLogDetailByList(String corpid, Long id, Integer moduleType,
                                                                Integer callTime, String target, Integer result) throws XbbException {
        if (isCallLogSyncTimesOutOfLimits(corpid, id)) {
            // 当前通话记录已经超过同步次数上限
            return null;
        }
        if (moduleType == CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode()) {
            String apiKey = callCenterOrganizationService.getApiKey(corpid, moduleType);
            DuYanCallLogResponseParamVO responseParamVO;
            // 可能存在的误差时间
            int errorTimeRange = 6;
            if (CallLogResultEnum.UN_SYNCED.getCode() == result) {
                // 手机端的误差时间设置为20秒
                errorTimeRange = 20;
            }
            try {
                responseParamVO = duYanHttpService.getCallLogList(apiKey, 1, 5, (callTime - errorTimeRange) * 1000L,
                        (callTime + errorTimeRange) * 1000L, null, null, target, null);
            } catch (XbbException e) {
                LOG.error("公司（%s）的通话记录（%d）获取度言通话记录列表来查询详情时出错：%s", corpid, id, e);
                return null;
            }
            if (responseParamVO == null || responseParamVO.getTotalElements() == null) {
                return null;
            }
            CallCenterCallLogEntity callCenterCallLogEntity = null;
            for (DuYanCallLogVO it : responseParamVO.getCallLogs()) {
                if (CallLogResultEnum.FAIL.getCode() == result && StringUtil.isEmpty(it.getCallUuid())) {
                    LOG.error("公司（%s）的失败的通话记录（%d）获取度言通话记录成功", corpid, id);
                    callCenterCallLogEntity = callCenterCommonService.packageDuYanCallLogEntity(callCenterCallLogEntity, it);
                    break;
                } else if (CallLogResultEnum.FAIL.getCode() != result && StringUtil.isNotEmpty(it.getCallUuid())) {
                    LOG.error("公司（%s）的通话记录（%d）获取度言通话记录成功，call_uuid：%s", corpid, id, it.getCallUuid());
                    callCenterCallLogEntity = callCenterCommonService.packageDuYanCallLogEntity(callCenterCallLogEntity, it);
                    // 成功的通话记录取记录中的最后一条
                }
            }
            if (callCenterCallLogEntity != null && StringUtil.isNotEmpty(callCenterCallLogEntity.getCallUuid())) {
                callCenterCallLogEntity.setCorpid(corpid);
                return callCenterCallLogEntity;
            }
            return null;
        }
        return null;
    }

    /**
     * 获取未接来电列表
     *
     * @param corpid     公司id
     * @param moduleType 第三方话务平台，参考AppStoreTypeEnum
     * @param userInfoVO 话务中心员工信息
     * @param page       页码
     * @param pageSize   页容量
     * @return List<CallCenterCallLogEntity> 通话记录列表
     * @throws XbbException 业务异常
     * @author youli.chen
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public CallLogListVO getMissedCallLogList(String corpid, Integer moduleType, CallCenterAccountUserInfoVO userInfoVO,
                                              Integer page, Integer pageSize) throws XbbException {
        CallLogListVO callLogListVO = new CallLogListVO();
        String apiKey = callCenterOrganizationService.getApiKey(corpid, moduleType);
        if (StringUtil.isEmpty(apiKey)) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301001);
        }
        DuYanCallLogResponseParamVO duYanCallLogResponseParamVO =
                duYanHttpService.getAgentMissedCallLogList(apiKey, userInfoVO.getAccountId(), page, pageSize);
        callLogListVO.setTotalPages(duYanCallLogResponseParamVO.getTotalPages());
        callLogListVO.setTotalElements(duYanCallLogResponseParamVO.getTotalElements());

        if (duYanCallLogResponseParamVO.getCallLogs() == null || Objects.equals(duYanCallLogResponseParamVO.getCallLogs().size(), 0)) {
            callLogListVO.setCallLogList(new ArrayList<>());
        } else {
            List<CallLogPojo> callLogs = new ArrayList<>();
            for (DuYanCallLogVO it : duYanCallLogResponseParamVO.getCallLogs()) {
                CallCenterFindRefDTO findRefDTO = callCenterCommonService.findRefByPhoneNum(corpid, it.getCaller());
                CallLogPojo callLogPojo = new CallLogPojo();
                callLogPojo.setCorpid(corpid);
                callLogPojo.setUserId(userInfoVO.getUserId());
                callLogPojo.setModuleType(moduleType);
                callLogPojo.setRefId(findRefDTO.getRefId());
                callLogPojo.setRefType(findRefDTO.getRefType());
                callLogPojo.setCallTime((int) (it.getCallTime() / 1000L));
                callLogPojo.setAnotherPhoneNum(it.getCaller());
                callLogPojo.setCallTimeShow(DateUtil.getString((int) (it.getCallTime() / 1000L), DateUtil.SDF));
                callLogPojo.setType(CallLogTypeEnum.INBOUND.getCode());
                callLogPojo.setResult(CallLogResultEnum.FAIL.getCode());
                callLogs.add(callLogPojo);
            }
            callLogListVO.setCallLogList(callLogs);
            // 将这批未接来电存入本地通话记录
            List<CallCenterCallLogEntity> callLogEntity = new ArrayList<>();
            try {
                BeanUtil.copyPropertiesList(callLogs, callLogEntity, CallCenterCallLogEntity.class);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            syncMissedCallLogList(corpid, userInfoVO.getUserId(), callLogEntity);
        }
        return callLogListVO;
    }

    /**
     * 移动端创建的通话记录需要同步
     *
     * @param corpid      公司Id
     * @param moduleType  话务中心平台类型
     * @param callLogList 通话记录列表
     * @throws XbbException 业务异常
     * @author youli.chen
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public void syncCallLog(final String corpid, final Integer moduleType, final List<CallCenterCallLogEntity> callLogList) throws XbbException {
        if (callLogList.size() > 0) {
            final String apiKey = callCenterOrganizationService.getApiKey(corpid, moduleType);
            if (StringUtil.isEmpty(apiKey)) {
                return;
            }

            //将本地数据库的通话记录去与度言比对同步，只能保证呼叫中心的数据被度言包含，不准确
            ThreadPoolHelper.getInstance().submitExecutorRunnable(callCenterThreadPool, new Runnable() {
                @Override
                public void run() {
                    for (CallCenterCallLogEntity it : callLogList) {
                        if (it.getIsSynced() != null && it.getIsSynced()) {
                            // 已经同步过的通话记录
                            continue;
                        }
                        CallCenterCallLogEntity origin = null;
                        if (StringUtil.isNotEmpty(it.getCallUuid())) {
                            try {
                                origin = callCenterCommonService.getOriginCallLogDetail(apiKey, it.getModuleType(), it.getCallUuid());
                            } catch (XbbException e) {
                                LOG.error("公司（%s）的通话记录（%d）获取详情时出错：%s", corpid, it.getId(), e);
                                origin = null;
                            }
                        }
                        if (origin == null) {
                            try {
                                origin = getOriginCallLogDetailByList(corpid, it.getId(), moduleType, it.getCallTime(),
                                        it.getAnotherPhoneNum(), it.getResult());
                            } catch (XbbException e) {
                                LOG.error("通过远程通话记录列表获取通话记录详情失败", e);
                            }
                            if (origin == null) {
                                continue;
                            }
                        }
                        // 定位到需要更新的文件，从数据库拿到完整信息
                        it = callCenterCallLogModel.getByKey(it.getId(), corpid);
                        if (it == null) {
                            try {
                                throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301057);
                            } catch (XbbException e) {
                                e.printStackTrace();
                                LOG.error("找不到需要更新的文件", e);
                            }
                        } else {
                            it.copyOriginDetail(origin);
                        }
                        try {
                            initRecordUrl(it);
                            callCenterCallLogModel.update(it);
                        } catch (XbbException e) {
                            e.printStackTrace();
                            LOG.error("通话记录更新失败", e);
                        }
                    }
                }
            });
        }
    }

    /**
     * 同步移动端近一天需要同步的通话记录
     *
     * @param corpid     公司Id
     * @param userId     用户Id
     * @param moduleType 话务中心平台类型
     * @throws XbbException 业务异常
     * @author youli.chen
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public void syncTodayMobileCallLog(String corpid, String userId, Integer moduleType) throws XbbException {
        ThreadPoolHelper.getInstance().submitExecutorRunnable(callCenterThreadPool, new Runnable() {
            @Override
            public void run() {
                Map<String, Object> params = new HashMap<>(6);
                params.put("corpid", corpid);
                params.put("userId", userId);
                params.put("result", CallLogResultEnum.UN_SYNCED.getCode());
                params.put("del", 0);
                Integer now = DateUtil.getInt();
                params.put("startUpdateTime", now - 86400);
                params.put("endUpdateTime", now);
                List<CallCenterCallLogEntity> list = callCenterCallLogModel.findEntitys(params);
                if (list.size() > 0) {
                    try {
                        syncCallLog(corpid, moduleType, list);
                    } catch (XbbException e) {
                        e.printStackTrace();
                        LOG.error("通话记录需要同步失败", e);
                    }
                }
            }
        });
    }

    /**
     * 提交翻译录音文件的任务
     *
     * @param callCenterCallLogEntity 通话录音
     * @param telPlat                 翻译的平台，小写字母拼写，参考StringConstant
     * @param callAudioTranslateVO    翻译录音文件的任务回参
     * @return callAudioTranslateVO    翻译录音文件的任务回参
     * @throws XbbException 封装异常
     * @author youli.chen
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public CallAudioTranslateVO submitTranslateTask(CallCenterCallLogEntity callCenterCallLogEntity, String telPlat, CallAudioTranslateVO callAudioTranslateVO) throws XbbException {
        if (!Objects.equals(callCenterCallLogEntity.getResult(), CallLogResultEnum.SUCCESS.getCode()) ||
                StringUtil.isEmpty(callCenterCallLogEntity.getRecordUrl())) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301058);
        }
        final String corpid = callCenterCallLogEntity.getCorpid();
        final Long logId = callCenterCallLogEntity.getId();
        if (StringUtil.isNotEmpty(callCenterCallLogEntity.getRecordContent())) {
            // 已经有语音转写的结果
            callAudioTranslateVO.setTaskResult(StringConstant.SUCCESS);
            // 翻译成功
            List<RecordContentPojo> recordContents = JSON.parseArray(callCenterCallLogEntity.getRecordContent(), RecordContentPojo.class);
            callAudioTranslateVO.setRecordContents(recordContents);
            return callAudioTranslateVO;
        }

        // 翻译任务防止重复提交
        String translateStatus = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_CALL_LOG_TRANSLATE_STATUS,
                corpid + StringConstant.COLON + logId);
        if (StringUtil.isNotEmpty(translateStatus)) {
            // 已经提交过任务
            callAudioTranslateVO.setTaskResult(translateStatus);
            return callAudioTranslateVO;
        }

        // 度言平台直接通过度言接口翻译
        if (Objects.equals(telPlat, StringConstant.PLATFORM_DUYAN)) {
            callAudioTranslateVO = duYanTelPlat(callCenterCallLogEntity, callAudioTranslateVO, corpid, logId);
        } else {
            // 非度言平台的通话记录直接通过中科院(讯飞)或阿里云平台进行翻译
            callAudioTranslateVO = notDuYanTelPlat(callCenterCallLogEntity, callAudioTranslateVO, corpid, logId, telPlat);
        }
        return callAudioTranslateVO;
    }

    /**
     * 计算该公司的通话总时长
     *
     * @param corpid 公司id
     * @return 通话时长
     * @throws XbbException 业务异常
     * @author youli.chen
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public Integer sumMonthlyCallDuration(String corpid) throws XbbException {
        return null;
    }

    /**
     * 获取最后一次通话时间
     *
     * @param corpid 公司id
     * @param userId 用户id
     * @return 通话时间10位int
     * @throws XbbException 业务异常
     * @author youli.chen
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public Integer getLastCallTime(String corpid, String userId) throws XbbException {
        return null;
    }

    /**
     * 获取录音文件的路径（获取后将更新持久层通话记录）直接拼接录音路径
     *
     * @param corpid                  公司id
     * @param moduleType              第三方话务平台，参考CallCenterTypeEnum
     * @param target                  通话号码
     * @param callTime                通话时间
     * @param callCenterCallLogEntity 本地存储的通话记录持久层对象
     * @return String 录音文件路径
     * @throws XbbException 业务异常
     * @author youli.chen
     * 创建时间：2019/1/15 下午7:00
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public String getCallLogRecordUrlStatic(String corpid, Integer moduleType, String target,
                                            Integer callTime, CallCenterCallLogEntity callCenterCallLogEntity) throws XbbException {
        if (moduleType == CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode()) {
            int result;
            if (callCenterCallLogEntity == null || callCenterCallLogEntity.getResult() == null) {
                result = CallLogResultEnum.UN_SYNCED.getCode();
            } else {
                result = callCenterCallLogEntity.getResult();
            }
            Long id = callCenterCallLogEntity == null ? null : callCenterCallLogEntity.getId();
            CallCenterCallLogEntity originCallLogEntity = getOriginCallLogDetailByList(corpid, id,
                    moduleType, callTime, target, result);
            if (originCallLogEntity != null) {
                // 获取录音文件的路径数据封装
                dyNamic(callCenterCallLogEntity, originCallLogEntity, corpid, target);
                return getCallLogRecordUrlByUuidStatic(corpid, moduleType, callCenterCallLogEntity);
            }
            return null;
        }
        return null;
    }

    /**
     * 获取录音文件的路径（获取后将更新持久层通话记录）直接拼接录音路径
     *
     * @param corpid                  公司id
     * @param moduleType              第三方话务平台，参考CallCenterTypeEnum
     * @param callCenterCallLogEntity 本地存储的通话记录持久层对象
     * @return String 录音文件路径
     * @throws XbbException 业务异常
     *                      创建时间：2019/1/15 下午7:00
     * @version v1.0
     * @since v1.0
     */
    @Override
    public String getCallLogRecordUrlByUuidStatic(String corpid, Integer moduleType,
                                                  CallCenterCallLogEntity callCenterCallLogEntity) throws XbbException {
        if (moduleType == CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode()) {
            CallCenterOrgGetByCorpIdVO org = callCenterOrganizationService.getByCorpId(corpid, moduleType);
            if (org == null) {
                throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301001);
            }
            String url = duYanHttpService.getRecordUrlStatic(org.getApikey(), org.getOrgId(),
                    DateUtil.getDateString(callCenterCallLogEntity.getCallTime()), callCenterCallLogEntity.getCallUuid());
            callCenterCallLogEntity.setRecordUrl(url);
            callCenterCallLogModel.save(callCenterCallLogEntity);
            return url;
        }
        return null;
    }

    /**
     * 获取录音文件的路径（获取后将更新持久层通话记录）通过API获取
     *
     * @param corpid                  公司id
     * @param moduleType              第三方话务平台，参考AppStoreTypeEnum
     * @param target                  通话号码
     * @param callTime                通话时间
     * @param callCenterCallLogEntity 本地存储的通话记录持久层对象
     * @return String 录音文件路径
     * @throws XbbException 业务异常
     * @author youli.chen
     * 创建时间：2019/1/15 上午9:30
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public String getCallLogRecordUrlDynamic(String corpid, Integer moduleType, String target, Integer callTime,
                                             CallCenterCallLogEntity callCenterCallLogEntity) throws XbbException {
        if (moduleType == CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode()) {
            int result;
            if (callCenterCallLogEntity == null || callCenterCallLogEntity.getResult() == null) {
                result = CallLogResultEnum.UN_SYNCED.getCode();
            } else {
                result = callCenterCallLogEntity.getResult();
            }
            Long id = callCenterCallLogEntity == null ? null : callCenterCallLogEntity.getId();
            CallCenterCallLogEntity originCallLogEntity = getOriginCallLogDetailByList(corpid, id, moduleType, callTime, target, result);
            if (originCallLogEntity != null) {
                // 获取录音文件的路径数据封装
                dyNamic(callCenterCallLogEntity, originCallLogEntity, corpid, target);
                return getCallLogRecordUrlByUuidDynamic(corpid, moduleType, callCenterCallLogEntity);
            }
            return null;
        }
        return null;
    }

    /**
     * 获取录音文件的路径（获取后将更新持久层通话记录）通过API获取
     *
     * @param corpid                  公司id
     * @param moduleType              第三方话务平台，参考AppStoreTypeEnum
     * @param callCenterCallLogEntity 本地存储的通话记录持久层对象
     * @return String 录音文件路径
     * @throws XbbException 业务异常
     * @author youli.chen
     * 创建时间：2019/1/15 上午9:30
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    @Override
    public String getCallLogRecordUrlByUuidDynamic(String corpid, Integer moduleType, CallCenterCallLogEntity callCenterCallLogEntity) throws XbbException {
        if (moduleType == CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode()) {
            CallCenterOrgGetByCorpIdVO org = callCenterOrganizationService.getByCorpId(corpid, moduleType);
            if (org == null) {
                throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301001);
            }
            String url = duYanHttpService.getRecordUrlDynamic(org.getApikey(), callCenterCallLogEntity.getCallUuid());
            callCenterCallLogEntity.setRecordUrl(url);
            callCenterCallLogModel.insert(callCenterCallLogEntity);
            return url;
        }
        return null;
    }

    /**
     * 通话录音语音转写
     *
     * @param callAudioTranslateDTO 通话录音语音转写入参
     * @return CallAudioTranslateVO  通话录音语音转写回参
     * @throws XbbException
     */
    @Override
    public CallAudioTranslateVO audioTranslate(CallAudioTranslateDTO callAudioTranslateDTO) throws XbbException {
        CallAudioTranslateVO callAudioTranslateVO = new CallAudioTranslateVO();
        String corpid = callAudioTranslateDTO.getCorpid();
        Long logId = callAudioTranslateDTO.getLogId();
        CallCenterCallLogEntity callCenterCallLogEntity = callCenterCallLogModel.getByKey(logId, corpid);
        if (callCenterCallLogEntity == null) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301059);
        }
        if(Objects.equals(callAudioTranslateDTO.getPlatform(), PlatFormEnum.WEB.getValue())){
            callAudioTranslateDTO.setTelPlat(StringConstant.PLATFORM_XBB);
        }
        callAudioTranslateVO = submitTranslateTask(callCenterCallLogEntity, callAudioTranslateDTO.getTelPlat(), callAudioTranslateVO);
        LOG.info("录音的转写结果--------打印一下---------："+ callAudioTranslateVO.getRecordContents());
        return callAudioTranslateVO;
    }

    /**
     * 新增一条阿里云呼通话记录
     * 此本新增只是在数据库先插入记录，具体内容待通话结束后保存
     *
     * @param aliyunCallCenterModelDTO 通话记录数据
     * @return 影响行数
     */
    @Override
    public Integer aliyunCallCenterInsert(AliyunCallCenterModelDTO aliyunCallCenterModelDTO) throws XbbException {
        // 通话ID和呼叫中心实例ID一定不能为空
        if (StringUtils.isBlank(aliyunCallCenterModelDTO.getCallId()) || StringUtils.isBlank(aliyunCallCenterModelDTO.getInstanceId())) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301055);
        }
        Map<String, Object> param = new HashMap<>(4);
        param.put("del", 0);
        param.put("callId", aliyunCallCenterModelDTO.getCallId());
        param.put("instanceId", aliyunCallCenterModelDTO.getInstanceId());
        param.put("callSource", CallCenterCallLogCallSourceEnum.ALIYUN_CALL_CENTER.getCode());
        param.put("corpid", aliyunCallCenterModelDTO.getCorpid());
        Integer count = callCenterCallLogModel.getEntitysCount(param);
        if (count > 0) {
            return 0;
        }
        return callCenterCallLogModel.aliyunCallCenterInsert(modelToEntity(aliyunCallCenterModelDTO));
    }

    @Override
    public Integer updateAliyunCallCenter(AliyunCallCenterModelDTO aliyunCallCenterModelDTO) throws XbbException {
        // 通话ID
        String callId = aliyunCallCenterModelDTO.getCallId();
        // 通话ID和呼叫中心实例ID一定不能为空
        if (StringUtils.isBlank(callId) || StringUtils.isBlank(aliyunCallCenterModelDTO.getInstanceId())) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301055);
        }
        // 用户ID
        String userId = aliyunCallCenterModelDTO.getUserId();
        // 公司ID
        String corpid = aliyunCallCenterModelDTO.getCorpid();
        // 校验登录用户
        UserEntity logUser = userModel.getByKey(userId, corpid);
        if (logUser == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.USER_NOT_EXIST);
        }
        // 根据通话ID查询通话记录
        Map<String, Object> param = new HashMap<>(3);
        param.put("corpid", corpid);
        param.put("callId", callId);
        param.put("del", DelEnum.NORMAL.getDel());
        List<CallCenterCallLogEntity> centerCallLogEntityList = callCenterCallLogModel.findEntitys(param);
        if (CollectionUtils.isEmpty(centerCallLogEntityList)) {
            return 0;
        }
        CallCenterCallLogEntity centerCallLogEntity = centerCallLogEntityList.get(0);
        // 如果已经同步则不需要再次同步
        if (centerCallLogEntity.getIsSynced()) {
            return 0;
        }
        // 将ID存起来
        CallCenterCallLogEntity callCenterCallLogEntity = modelToEntity(aliyunCallCenterModelDTO);
        callCenterCallLogEntity.setUserName(aliyunCallCenterModelDTO.getCallUserNames());
        callCenterCallLogEntity.setUserId(aliyunCallCenterModelDTO.getCallUserIds());
        callCenterCallLogEntity.setId(centerCallLogEntity.getId());
        callCenterCallLogEntity.setRecordUrl(aliyunCallCenterModelDTO.getRecordUrl());
        // 客户号码
        String aliyunSteasPhoneNum = Objects.nonNull(aliyunCallCenterModelDTO.getType()) && aliyunCallCenterModelDTO.getType().equals(0) ? aliyunCallCenterModelDTO.getAgentPhoneNum() : aliyunCallCenterModelDTO.getAnotherPhoneNum() ;
        // 根据公司ID和电话查询线索
        CustomerEntityExt cusEntityExt = customerModel.getByPhoneIncloudRecycled(aliyunCallCenterModelDTO.getCorpid(), aliyunSteasPhoneNum);
        ContactEntityExt contactEntityExt = null;
        if (cusEntityExt != null) {
            callCenterCallLogEntity.setRefId(cusEntityExt.getId());
            String name = FastJsonHelper.getStringOrDefaultFromFormData(cusEntityExt.getData(), CustomerManagementEnum.NAME.getAttr(), "");
            callCenterCallLogEntity.setRefName(name);
            callCenterCallLogEntity.setRefType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
        } else {
            // 联系人
            contactEntityExt = contactModel.getByPhone(corpid, aliyunSteasPhoneNum);
            if (contactEntityExt != null) {
                Long contactId = contactEntityExt.getId();
                callCenterCallLogEntity.setRefId(contactId);
                String name = FastJsonHelper.getStringOrDefaultFromFormData(contactEntityExt.getData(), ContactEnum.NAME.getAttr(), "");
                callCenterCallLogEntity.setRefName(name);
                callCenterCallLogEntity.setRefType(XbbRefTypeEnum.CONTACT.getCode());
            }
        }
        if (cusEntityExt == null && contactEntityExt == null) {
            // 线索
            ClueEntityExt clueEntityExt = clueModel.getByPhoneIncloudRecycled(corpid, aliyunSteasPhoneNum);
            if (clueEntityExt != null) {
                Long clueId = clueEntityExt.getId();
                callCenterCallLogEntity.setRefId(clueId);
                String name = FastJsonHelper.getStringOrDefaultFromFormData(clueEntityExt.getData(), ClueEnum.COMPANY_NAME.getAttr(), "");
                callCenterCallLogEntity.setRefName(name);
                callCenterCallLogEntity.setRefType(XbbRefTypeEnum.CLUE.getCode());
            } else {
                LOG.info("-----404-----");
                callCenterCallLogEntity.setRefId(0L);
                callCenterCallLogEntity.setRefName("--");
                callCenterCallLogEntity.setRefType(CallCenterTypeEnum.UNKNOWN.getCode());
            }
        }
        callCenterCallLogEntity.setIsSynced(true);
        // 添加跟进记录
        List list = new ArrayList();
        list.add(callCenterCallLogEntity);
        Integer res = callCenterCallLogModel.updateAliyunCallCenter(callCenterCallLogEntity);
        saveCommunicate(list,aliyunCallCenterModelDTO);
        return res;
    }

    @Override
    public AliyunCallcenterListVO aliyunCallCenterList(AliyunCallCenterListDTO aliyunCallCenterListDTO) throws XbbException {
        // 用户ID
        String userId = aliyunCallCenterListDTO.getUserId();
        // 公司ID
        String corpid = aliyunCallCenterListDTO.getCorpid();
        // 校验登录用户
        UserEntity logUser = userModel.getByKey(userId, corpid);
        if (logUser == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.USER_NOT_EXIST);
        }
        // 查询ES
        return aliyunCallCenterRecordList(aliyunCallCenterListDTO);
    }

    @Override
    public AliyunCallcenterRecentlyRecordVO findRecentlyCallRecord(AliyunCallcenterRecentlyRecordDTO recentlyRecordDTO) throws XbbException {
        IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG;
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, recentlyRecordDTO.getCorpid()));
        long nowTime = DateUtil.getLong();
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(nowTime);
        cal.add(Calendar.HOUR_OF_DAY, -48);
        long startTime = cal.getTimeInMillis() / 1000;
        long endTime = nowTime / 1000;
        boolQueryBuilder.filter(rangeQuery("addTime").gte(startTime).lt(endTime));
        boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(rangeQuery("type").gte(BasicConstant.ZERO).lte(BasicConstant.ZERO));
        boolQueryBuilder.filter(termQuery("agentPhoneNum", recentlyRecordDTO.getNumber()));
        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 搜索条件
        EsUtil.setPage(sourceBuilder, 1, 1000);
        sourceBuilder.query(boolQueryBuilder);
        sourceBuilder.sort(new FieldSortBuilder("addTime").order(SortOrder.DESC));
        //设置查询路由
        SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
        searchRequest.source(sourceBuilder);
        // 先查询最近的一次通话记录
        List<CallCenterCallLogEntity> logEntities = xbbElasticsearchRestTemplate.queryForList(searchRequest, CallCenterCallLogEntity.class);
        AliyunCallcenterRecentlyRecordVO recordVO = new AliyunCallcenterRecentlyRecordVO();
        // 如果不存在就就说明48小时之内不可能有通话记录，直接返回
        long recentlyCallNumber = 0;
        String recentlyCallTime = "";
        if (CollectionUtils.isNotEmpty(logEntities)) {
            recentlyCallNumber = logEntities.size();
            CallCenterCallLogEntity entity = logEntities.get(0);
            recentlyCallTime = DateUtil.getString(entity.getAddTime(), DateUtil.SDFYMDHM);
        }
        recordVO.setRecentlyCallNumber(recentlyCallNumber);
        recordVO.setRecentlyCallTime(recentlyCallTime);
        return recordVO;
    }

    @Override
    public List<ItemDataPoJo> findAliyunCallRecordCondition(AliyunCallRecordConditionReqDTO conditionReqDTO) throws XbbException {
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, conditionReqDTO.getCorpid()));
        // 条件
        String condition = conditionReqDTO.getCondition();
        // 字段
        String field = conditionReqDTO.getField();
        // 查询字段
        List<String> fieldList = new ArrayList<>();
        fieldList.add(field);
        if (StringUtils.isNotBlank(condition)) {
            BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
            innerBoolQueryBuilder.should(QueryBuilders.matchPhrasePrefixQuery(field, condition));
            innerBoolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
            boolQueryBuilder.filter(innerBoolQueryBuilder);
        }
        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG.getType()));
        boolQueryBuilder.filter(termsQuery("callSource", CallCenterCallLogCallSourceEnum.listYunCallCallSource()));
        if (CollectionUtils.isNotEmpty(conditionReqDTO.getSearchUserIdList())){
            boolQueryBuilder.filter(termsQuery("userId", conditionReqDTO.getSearchUserIdList().toArray()));
        }
        // 其他字段
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //设置查询条件
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        NativeSearchQuery searchQuery = nativeSearchQueryBuilder.build();
        sourceBuilder.query(searchQuery.getQuery());
        EsUtil.setFieldList(sourceBuilder, fieldList);
        SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG.getIndex());
        // 去重
        sourceBuilder.collapse(new CollapseBuilder(field +".keyword"));
        searchRequest.source(sourceBuilder);
        PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 1, 10);
        List<JSONObject> conditionList = xbbElasticsearchRestTemplate.queryForList(pageRequest, searchRequest, JSONObject.class);
        if (CollectionUtils.isEmpty(conditionList)) {
            return new ArrayList<>();
        }
        return conditionList.stream().filter(json -> StringUtils.isNotBlank(json.getString(conditionReqDTO.getField())))
                .map(json -> {
                    ItemDataPoJo itemDataPoJo = new ItemDataPoJo();
                    Object value = json.get(conditionReqDTO.getField());
                    itemDataPoJo.setText(value);
                    itemDataPoJo.setValue(value);
                    return itemDataPoJo;
                }).collect(Collectors.toList());
    }

    @Override
    public AliyunCallUserInfoConditionVO findUserInfoCondition(AliyunCallUserInfoConditionReqDTO userInfoConditionReqDTO) throws XbbException {
        AliyunCallUserInfoConditionVO aliyunCallUserInfoConditionVO = new AliyunCallUserInfoConditionVO();
        try{
            UserVO loginUser = userInfoConditionReqDTO.getLoginUser();
            aliyunCallUserInfoConditionVO.setNew(false);
            aliyunCallUserInfoConditionVO.setShowCommunicate(false);
            boolean numberVisible= true;
            String corpid = userInfoConditionReqDTO.getCorpid();
            String userId = userInfoConditionReqDTO.getUserId();
            Integer moduleType = 0;
            String anotherPhoneNum = userInfoConditionReqDTO.getAnotherPhoneNum();
            PaasFormDataEntityExt paasFormDataEntityExt = null;

            // 客户
            CustomerEntityExt cusEntityExt = customerModel.getByPhoneIncloudRecycled(corpid, anotherPhoneNum);
            ContactEntityExt contactEntityExt = null;
            String customerId = "";
            Integer subBusinessType = null;
            Integer businessType= null;
            Long appId = 0L;
            Long formId = 0L;
            Long dataId =0L;
            Long menuId = 0L;
            Integer saasMark = SaasMarkEnum.SAAS.getCode();
            if (cusEntityExt != null) {
                aliyunCallUserInfoConditionVO.setRefId(cusEntityExt.getId());
                aliyunCallUserInfoConditionVO.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(cusEntityExt.getData(), CustomerManagementEnum.NAME.getAttr(), ""));
                aliyunCallUserInfoConditionVO.setRefType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                paasFormDataEntityExt = cusEntityExt;
                paasFormDataEntityExt.setSaasMark(SaasMarkEnum.SAAS.getCode());
                businessType = ListBusinessTypeEnum.CUSTOMER_MANAGEMENT.getBusinessType();
                subBusinessType = ListBusinessTypeEnum.CUSTOMER_MANAGEMENT.getSubBusinessType();
            } else if (cusEntityExt == null) {
                // 联系人
                contactEntityExt = contactModel.getByPhone(corpid, anotherPhoneNum);
                if (contactEntityExt != null) {
                    Long contactId = contactEntityExt.getId();
                    aliyunCallUserInfoConditionVO.setRefId(contactId);
                    aliyunCallUserInfoConditionVO.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(contactEntityExt.getData(), ContactEnum.NAME.getAttr(), ""));
                    aliyunCallUserInfoConditionVO.setRefType(XbbRefTypeEnum.CONTACT.getCode());
                    paasFormDataEntityExt = contactEntityExt;
                    paasFormDataEntityExt.setSaasMark(SaasMarkEnum.SAAS.getCode());
                    businessType = ListBusinessTypeEnum.CONTACT.getBusinessType();
                    subBusinessType = ListBusinessTypeEnum.CONTACT.getSubBusinessType();
                }else if (contactEntityExt == null){
                    // 线索
                    ClueEntityExt clueEntityExt = clueModel.getByPhoneIncloudRecycled(corpid, anotherPhoneNum);
                    if (clueEntityExt != null) {
                        Long clueId = clueEntityExt.getId();
                        aliyunCallUserInfoConditionVO.setRefId(clueId);
                        aliyunCallUserInfoConditionVO.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(clueEntityExt.getData(), ClueEnum.COMPANY_NAME.getAttr(), ""));
                        aliyunCallUserInfoConditionVO.setRefType(XbbRefTypeEnum.CLUE.getCode());
                        paasFormDataEntityExt = clueEntityExt;
                        paasFormDataEntityExt.setSaasMark(SaasMarkEnum.SAAS.getCode());
                        businessType = ListBusinessTypeEnum.CLUE.getBusinessType();
                        subBusinessType = ListBusinessTypeEnum.CLUE.getSubBusinessType();
                    }
                }
            }
            if(paasFormDataEntityExt==null){
                // 当前登陆人有权限的客户表单模版
                List<PaasFormEntityExt> paasFormEntityExtList = paasFormService.getEnableCustomerFormList(loginUser);
                if (paasFormEntityExtList.isEmpty()) {
                    throw new XbbException(ClueErrorCodeEnum.API_ERROR_1110013);
                }
                // 客户的第一个表单模版
                PaasFormEntityExt entityExt = paasFormEntityExtList.get(0);
                aliyunCallUserInfoConditionVO.setMenuId(entityExt.getMenuId());
                aliyunCallUserInfoConditionVO.setFormId(entityExt.getId());
                aliyunCallUserInfoConditionVO.setAppId(entityExt.getAppId());
                aliyunCallUserInfoConditionVO.setSaasMark(SaasMarkEnum.SAAS.getCode());
                aliyunCallUserInfoConditionVO.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                aliyunCallUserInfoConditionVO.setSubBusinessType(XbbRefTypeEnum.CUSTOMER.getCode());
                aliyunCallUserInfoConditionVO.setRefName(I18nMessageUtil.getMessage("constant.chartI18Constant.system_no_matching_information"));
                aliyunCallUserInfoConditionVO.setNew(true);
                aliyunCallUserInfoConditionVO.setVisible(true);
                return aliyunCallUserInfoConditionVO;
            }else{
                appId = paasFormDataEntityExt.getAppId();
                formId = paasFormDataEntityExt.getFormId();
                dataId = paasFormDataEntityExt.getDataId();
                menuId = paasFormDataEntityExt.getMenuId();
                numberVisible = getNumberVisibleh(businessType, anotherPhoneNum, userInfoConditionReqDTO);
            }
            //根据formId查询解释
            PaasFormExplainEntity explain = paasFormExplainModel.getByFormId(formId, paasFormDataEntityExt.getCorpid());
            if (Objects.isNull(explain)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            //-------------
           // 判断是否有跟进记录新建权限
            VerifyViewPermissionDTO verifyViewPermissionDTO = new VerifyViewPermissionDTO();
            verifyViewPermissionDTO.setLoginUser(loginUser);
            verifyViewPermissionDTO.setSaasMark(saasMark);
            verifyViewPermissionDTO.setBusinessType(XbbRefTypeEnum.CUSTOMER_COMMUNICATE.getCode());
            verifyViewPermissionDTO.setPaasFormDataEntityExt(paasFormDataEntityExt);
            // 编辑权限校验
            VerifyUpdatePermissionDTO verifyUpdatePermissionDTO = new VerifyUpdatePermissionDTO();
            verifyUpdatePermissionDTO.setLoginUser(loginUser);
            verifyUpdatePermissionDTO.setSaasMark(saasMark);
            verifyUpdatePermissionDTO.setBusinessType(XbbRefTypeEnum.CUSTOMER_COMMUNICATE.getCode());
            Set<String> permSet = loginUser.getPermSet();
            TransmittableThreadLocalUtil.setValue(saasMark, businessType, menuId, 0);
            // 去获取表单模板中的信息
            List<FieldAttrEntity> explainList = JSONArray.parseArray(explain.getExplains(), FieldAttrEntity.class);
            PaasFormEntityExt paasFormEntityExt = paasFormModel.getByKey(paasFormDataEntityExt.getFormId(), corpid);
            HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
            BeanUtil.copyProperties(userInfoConditionReqDTO, handlerExplainDTO, false);
            handlerExplainDTO.setCreatorId(paasFormDataEntityExt.getCreatorId());
            UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
            BeanUtil.copyProperties(userInfoConditionReqDTO, userAndDepartmentGetDTO);
            userAndDepartmentGetDTO.setExplainList(explainList);
            Map<String, UserEntity> userMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            handlerExplainDTO.setExplainList(explainList);
            // 获取协同人和负责人
            paasFormHelp.getOwnerIdAndCoUserId(handlerExplainDTO, saasMark, businessType, businessType, paasFormDataEntityExt, userMap);
            paasFormDataEntityExt.getData().put(FieldTypeEnum.OWNERID.getAlias(), handlerExplainDTO.getOwnerId());
            paasFormDataEntityExt.getData().put(FieldTypeEnum.COUSERID.getAlias(), handlerExplainDTO.getCoUserId());
            // 校验权限
            boolean hasDataPermission = commonPermissionHelp.checkViewPermission(verifyViewPermissionDTO);
            if(permSet.contains(ProPermissionAliasEnum.CUSTOMER_COMMUNICATE_VIEW.getAlias())
                    &&permSet.contains(ProPermissionAliasEnum.CUSTOMER_COMMUNICATE_ADD.getAlias())
                    && hasDataPermission){
                aliyunCallUserInfoConditionVO.setShowCommunicate(true);
            }else{
                aliyunCallUserInfoConditionVO.setShowCommunicate(false);
            }
            handlerExplainDTO.setPaasFormEntityExt(paasFormEntityExt);
            handlerExplainDTO.setFormData(paasFormDataEntityExt.getData());
            // 获取表单解释
            HandlerExplainVO handlerExplainVO = formDataDetailFormExplainHandleName.handleExplain(handlerExplainDTO);
            Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(JSONObject.toJSONString(handlerExplainVO.getHeadList()), null);

            //-------------
    //        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explain.getExplains(), null);
            //协同团队
            Map<Long, List<String>> mainUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<Long, List<String>> coUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            userTeamService.getUserIdMap(Collections.singletonList(paasFormDataEntityExt.getDataId()),corpid,businessType,false,mainUserMap,coUserMap);
            List<UserEntity> mainUserList = new ArrayList<>();
            List<UserEntity> coUserList = new ArrayList<>();
            if(mainUserMap.get(dataId)!=null){
                mainUserList = userModel.findEntitysByUserIds(mainUserMap.get(dataId), corpid);
            }
            if(coUserMap.get(dataId)!=null){
                coUserList = userModel.findEntitysByUserIds(coUserMap.get(dataId), corpid);
            }
            StringBuffer mainUserListStr = new StringBuffer();
            for(UserEntity temp:mainUserList){
                mainUserListStr.append(temp.getName());
            }
            StringBuffer coUserListStr = new StringBuffer();
            for(UserEntity temp:coUserList){
                coUserListStr.append(temp.getName());
            }
            String creatorId = paasFormDataEntityExt.getCreatorId();
            StringBuffer creatorIdListStr = new StringBuffer();
            if(Objects.nonNull(creatorId)){
                List creatorIdList = new ArrayList();
                creatorIdList.add(creatorId);
                List<UserEntity> creatorList = userModel.findEntitysByUserIds(creatorIdList, corpid);
                for(UserEntity temp:creatorList){
                    creatorIdListStr.append(temp.getName());
                }
                paasFormDataEntityExt.getData().put(FieldTypeEnum.CREATORID.getAlias(),mainUserListStr);
            }

            paasFormDataEntityExt.getData().put(FieldTypeEnum.OWNERID.getAlias(), mainUserListStr);
            paasFormDataEntityExt.getData().put(FieldTypeEnum.COUSERID.getAlias(), coUserListStr);
    //        JSONObject dataJsonObject =  paasFormDataEntityExt.getData();
            List<SummaryDataPoJo> summaryList = paasFormHelp.getSummaryList(paasFormEntityExt, explainMap, paasFormDataEntityExt);
            setSummaryDefaultValue(summaryList);
            JSONArray labelsList = null;
            JSONObject paasFormDataEntityExtData = paasFormDataEntityExt.getData();
            PaasFormExplainEntity communicateExplain = paasFormExplainModel.getByFormId(formId, corpid);
            List<FieldAttrEntity> communicateExplainList = JSONArray.parseArray(communicateExplain.getExplains(), FieldAttrEntity.class);
            String attr = null;
            boolean showLableList = false;
            for(FieldAttrEntity entity:communicateExplainList){
                if (Objects.equals(entity.getIsOpen(),1)&&Objects.equals(FieldTypeEnum.LABEL.getType(), entity.getFieldType())){
                    attr = entity.getAttr();
                    showLableList = true;
                    break;
                }
            }
            labelsList = (JSONArray)paasFormDataEntityExtData.get(attr);
            if(labelsList==null){
                labelsList = new JSONArray();
            }
            //跟进记录标签
            if(showLableList){
                LabelListDTO labelListDTO = new LabelListDTO();
                labelListDTO.setFormId(formId);
                labelListDTO.setBusinessType(aliyunCallUserInfoConditionVO.getRefType());
                labelListDTO.setAppId(appId);
                labelListDTO.setIsReLabel(0);
                labelListDTO.setCorpid(corpid);
                labelListDTO.setNameLike(userInfoConditionReqDTO.getNameLike());
                labelListDTO.setUserId(userId);
                LabelShowVO allLabelList = labelService.getAllLabelList(labelListDTO);
                aliyunCallUserInfoConditionVO.setLabelTreePojos(allLabelList.getLabelTreePojos());
            }else{
                aliyunCallUserInfoConditionVO.setLabelTreePojos(new ArrayList<>());
            }
            aliyunCallUserInfoConditionVO.setLabelsList(labelsList);
            aliyunCallUserInfoConditionVO.setSummaryList(summaryList);
            aliyunCallUserInfoConditionVO.setFormId(formId);
            aliyunCallUserInfoConditionVO.setSubBusinessType(subBusinessType);
            aliyunCallUserInfoConditionVO.setBusinessType(businessType);
            aliyunCallUserInfoConditionVO.setAppId(appId);
            aliyunCallUserInfoConditionVO.setDataId(dataId);
            aliyunCallUserInfoConditionVO.setMenuId(menuId);
            aliyunCallUserInfoConditionVO.setSaasMark(saasMark);
            aliyunCallUserInfoConditionVO.setVisible(numberVisible);
        }catch (Exception e){
            LOG.error("==findUserInfoCondition==",e);
            throw e;
        }
        return aliyunCallUserInfoConditionVO;
    }

    public void saveCommunicate(List<CallCenterCallLogEntity> list, BaseDTO BaseDTO)throws XbbException{
        new Thread(()->{
            LOG.info("=========={}==========","开始添加跟进记录");
            for(CallCenterCallLogEntity callLogEntity: list){
                AliyunCallSaveCommunicateReqDTO dto = new AliyunCallSaveCommunicateReqDTO();
                BeanUtils.copyProperties(BaseDTO, dto);
                BeanUtils.copyProperties(callLogEntity, dto);
                String userId = callLogEntity.getUserId();
                String corpid = callLogEntity.getCorpid();
                Integer result = callLogEntity.getResult();
                Integer type = callLogEntity.getType();
                Integer addTime = callLogEntity.getAddTime();
                dto.setStartTime(addTime);
                dto.setType(type);
                if(AliyunCallCenterResultEnum.SUCCESS.getCode()==result){
                    dto.setNotConnected(false);
                }else {
                    dto.setNotConnected(true);
                }
                try {
                    if(Objects.nonNull(userId)){
                        String[] split = userId.split(",");
                        if (split != null && split.length > 0) {
                            userId = split[0];
                            dto.setUserId(userId);
                        }
                    }else {
                        continue;
                    }
                    UserVO userVO = userModel.getUserVO(corpid, userId, true, true);
                    dto.setLoginUser(userVO);
                    if("dinga93c84f4d89688bf35c2f4657eb6378f".equals(corpid)){
                        LOG.info("==========dto:{}==========",dto);
                    }
                    saveCommunicate(dto);
                }catch (Exception e){
                    if("dinga93c84f4d89688bf35c2f4657eb6378f".equals(corpid)){
                        LOG.info("==========e:{}==========",e);
                    }
                }
            }
            LOG.info("=========={}==========","结束添加跟进记录");
        }).start();
    }

    @Override
    public AddCommunicateVO saveCommunicate(AliyunCallSaveCommunicateReqDTO aliyunCallSaveCommunicateReqDTO) throws XbbException {
        String corpid = aliyunCallSaveCommunicateReqDTO.getCorpid();
        String userId = aliyunCallSaveCommunicateReqDTO.getUserId();
        Long refId = aliyunCallSaveCommunicateReqDTO.getRefId();
        String platform = aliyunCallSaveCommunicateReqDTO.getPlatform();
        Integer refType = aliyunCallSaveCommunicateReqDTO.getRefType();
        String content = aliyunCallSaveCommunicateReqDTO.getContent();
        String dynamicContent = aliyunCallSaveCommunicateReqDTO.getContent();
        List<Long> dataIdList = aliyunCallSaveCommunicateReqDTO.getDataIdList();
        Boolean notConnected = aliyunCallSaveCommunicateReqDTO.getNotConnected();
        Integer type = aliyunCallSaveCommunicateReqDTO.getType();
        String anotherPhoneNum = aliyunCallSaveCommunicateReqDTO.getAnotherPhoneNum();
        Integer startTime = aliyunCallSaveCommunicateReqDTO.getStartTime();
        //此判断是非直接调接口才用  工作台的保存跟进记录是不传type和notConnected参数的
        Integer isAuto = 0;
        if(type!=null&&notConnected!=null){
            isAuto = 1;
            if(type!=0){  //呼出
                anotherPhoneNum = aliyunCallSaveCommunicateReqDTO.getAnotherPhoneNum();
//                agentPhoneNum = aliyunCallSaveCommunicateReqDTO.getAgentPhoneNum();
                Boolean numberVisibleh = getNumberVisibleh( anotherPhoneNum, aliyunCallSaveCommunicateReqDTO);
                if(numberVisibleh==null||numberVisibleh==false){
                    anotherPhoneNum = getHideNumber(anotherPhoneNum);
                }
                if(notConnected){
                    content =String.format(I18nMessageUtil.getMessage(I18nStringConstant.CALL_NOT_CONNECTED), anotherPhoneNum);
                    dynamicContent =String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.CALL_NOT_CONNECTED), anotherPhoneNum);
                }else{
                    content =String.format(I18nMessageUtil.getMessage(I18nStringConstant.CALL_CONNECTED), anotherPhoneNum);
                    dynamicContent =String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.CALL_CONNECTED), anotherPhoneNum);
                }
            }else{
                anotherPhoneNum =  aliyunCallSaveCommunicateReqDTO.getAgentPhoneNum();
//                agentPhoneNum =aliyunCallSaveCommunicateReqDTO.getAnotherPhoneNum();
                Boolean numberVisibleh = getNumberVisibleh( anotherPhoneNum, aliyunCallSaveCommunicateReqDTO);
                if(numberVisibleh==null||numberVisibleh==false){
                    anotherPhoneNum = getHideNumber(anotherPhoneNum);
                }
                if(notConnected){
                    content =String.format(I18nMessageUtil.getMessage(I18nStringConstant.ANSWER_NOT_CONNECTED), anotherPhoneNum);
                    dynamicContent =String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.ANSWER_NOT_CONNECTED), anotherPhoneNum);
                }else{
                    content =String.format(I18nMessageUtil.getMessage(I18nStringConstant.ANSWER_CONNECTED), anotherPhoneNum);
                    dynamicContent =String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.ANSWER_CONNECTED), anotherPhoneNum);
                }
            }
        }

         // 存在通话对象
        AddCommunicateDTO addCommunicateDTO = new AddCommunicateDTO();
        addCommunicateDTO.setCorpid(corpid);
        addCommunicateDTO.setUserId(userId);
        addCommunicateDTO.setPlatform(platform);
        addCommunicateDTO.setModuleType(CallCenterTypeEnum.CALL_CENTER_ALI_YUN.getCode());
        addCommunicateDTO.setRefId(refId);
        addCommunicateDTO.setRefType(refType);
        addCommunicateDTO.setAnotherPhoneNum(anotherPhoneNum);
        addCommunicateDTO.setContent(content);
        addCommunicateDTO.setDynamicContent(dynamicContent);
        addCommunicateDTO.setDataIdList(dataIdList);
        addCommunicateDTO.setStartTime(startTime);
        addCommunicateDTO.setIsAuto(isAuto);
        AddCommunicateVO addCommunicateVO = callCenterCommonService.addCommunicate(addCommunicateDTO);
        return addCommunicateVO;
    }

    /**
     * 数据库实体类转POJO
     *
     * @param callCenterCallLogEntity 数据库实体类
     * @return POJO
     */
    private AliyunCallCenterPojo entityToPojo(CallCenterCallLogEntity callCenterCallLogEntity) {
        AliyunCallCenterPojo aliyunCallCenterPojo = new AliyunCallCenterPojo();
        BeanUtils.copyProperties(callCenterCallLogEntity, aliyunCallCenterPojo);
        return aliyunCallCenterPojo;
    }

    /**
     * 获取录音文件的路径数据封装
     *
     * @param callCenterCallLogEntity 通话记录实体类
     * @param originCallLogEntity     通过远程通话记录列表获取通话记录详情
     * @param corpid                  公司ID
     * @param target                  电话
     * @throws XbbException
     */
    private void dyNamic(CallCenterCallLogEntity callCenterCallLogEntity, CallCenterCallLogEntity originCallLogEntity,
                         String corpid, String target) throws XbbException {
        if (callCenterCallLogEntity == null) {
            callCenterCallLogEntity = originCallLogEntity;
            CallCenterFindRefDTO findRefDTO = callCenterCommonService.findRefByPhoneNum(corpid, target);
            callCenterCallLogEntity.setRefId(findRefDTO.getRefId());
            callCenterCallLogEntity.setRefType(findRefDTO.getRefType());
            callCenterCallLogEntity.setRefName(findRefDTO.getRefName());
        } else {
            callCenterCallLogEntity.copyOriginDetail(originCallLogEntity);
        }
    }

    /**
     * 获取对象名称
     *
     * @param corpid  公司ID
     * @param refId   对象ID
     * @param refType 对象类型
     * @return 对象名称
     */
    private String getRefName(String corpid, Long refId, Integer refType) {
        XbbRefTypeEnum refTypeEnum = XbbRefTypeEnum.getByCode(refType);
        switch (refTypeEnum) {
            case CUSTOMER:
                CustomerEntityExt customerEntityExt = customerModel.getByKey(refId, corpid);
                if (customerEntityExt == null || customerEntityExt.getDel() == 1) {
                    return null;
                }
                return customerEntityExt.getData().getString(CustomerManagementEnum.NAME.getAttr());
            case CONTACT:
                ContactEntityExt contactEntityExt = contactModel.getByKey(refId, corpid);
                if (contactEntityExt == null || contactEntityExt.getDel() == 1) {
                    return null;
                }
                return contactEntityExt.getData().getString(ContactEnum.NAME.getAttr());
            default:
                return null;
        }
    }

    /**
     * 判断通话记录的同步次数是否超标
     *
     * @param corpid 公司id
     * @param id     通话记录主键
     * @return boolean 是否超标
     * @author 章华隽
     * 创建时间：2017/12/28 下午3:12
     * 修改时间：2018/01/10 晚上8:56 by 章华隽
     * @version 3.16
     * @since 3.15.1
     */
    private boolean isCallLogSyncTimesOutOfLimits(String corpid, Long id) {
        if (StringUtil.isEmpty(corpid) || id == null) {
            return false;
        }
        String lastCallLogSyncTimeStr = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_CALL_LOG_LAST_SYNC_TIME,
                corpid + StringConstant.COLON + id);
        int now = DateUtil.getInt();
        int lastSyncTime;
        if (StringUtil.isEmpty(lastCallLogSyncTimeStr)) {
            // 第一次进行校验
            lastSyncTime = now;
            paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_CALL_LOG_LAST_SYNC_TIME, corpid + StringConstant.COLON + id,
                    String.valueOf(lastSyncTime), RedisConstant.HUGE_DURATION);
        } else {
            lastSyncTime = Integer.parseInt(lastCallLogSyncTimeStr);
        }
        // 12小时的秒数
        int halfDaySeconds = 43200;
        if (now - lastSyncTime > halfDaySeconds) {
            // 如果一个通话记录超过12小时同步仍然没有结果则删除
            callCenterCallLogModel.deleteByKey(id, corpid);
            paasRedisHelper.removeValue(CallCenterConstant.REDIS_KEY_CALL_LOG_LAST_SYNC_TIME, corpid + StringConstant.COLON + id);
            return true;
        } else {
            return false;
        }
    }

    /**
     * 获取通话记录的基本参数封装
     *
     * @param boolQueryBuilder     按权限设置的参数
     * @param callCallLogListDTO 基本请求参数
     * @return CallLogListVO 封装的通话记录
     * @author youli.chen
     * @version v1.0
     * @since v1.0
     */
    private CallLogListVO getCallLogList(BoolQueryBuilder boolQueryBuilder, CallCallLogListDTO callCallLogListDTO) throws XbbException {
        CallLogListVO callLogListVO = new CallLogListVO();
        PageHelper pageHelper;
        List<CallCenterCallLogEntity> callLogEntityList;
        try {
            boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT+ StringConstant.KEY_WORD, callCallLogListDTO.getCorpid()));
            RangeQueryBuilder callTimeQuery = null;
            if (Objects.nonNull(callCallLogListDTO.getStartTime())) {
                callTimeQuery = rangeQuery("callTime");
                callTimeQuery.gte(callCallLogListDTO.getStartTime());
            }
            if (Objects.nonNull(callCallLogListDTO.getEndTime())) {
                if(callTimeQuery == null){
                    callTimeQuery = rangeQuery("callTime");
                }
                callTimeQuery.lt(callCallLogListDTO.getEndTime());
            }
            //有一个不为空就可以加入
            if(callTimeQuery != null){
                boolQueryBuilder.filter(callTimeQuery);
            }
            Integer businessType = callCallLogListDTO.getBusinessType();
            if (callCallLogListDTO.getDataId() != null && businessType != null) {
                // 按对象查找通话记录，客户可以拿到所有隶属联系人的通话记录
                int codeCustomer = XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode();
                if (Objects.equals(businessType, codeCustomer)) {
                    List<Long> contactIdIn = contactModel.getCallLogCustomerContactIdList(callCallLogListDTO.getCorpid(), callCallLogListDTO.getDataId(), callCallLogListDTO.getPageSize());
                    if (contactIdIn.size() > 0) {
                        BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
                        BoolQueryBuilder contactBool = boolQuery();
                        contactBool.filter(termsQuery("refId", contactIdIn));
                        int codeContact = XbbRefTypeEnum.CONTACT.getCode();
                        contactBool.filter(rangeQuery("refType").gte(codeContact).lte(codeContact));
                        innerBoolQueryBuilder.should(contactBool);
                        BoolQueryBuilder customerBool = boolQuery();
                        customerBool.filter(termQuery("refId", callCallLogListDTO.getDataId()));
                        customerBool.filter(rangeQuery("refType").gte(codeCustomer).lte(codeCustomer));
                        innerBoolQueryBuilder.should(customerBool);
                        innerBoolQueryBuilder.minimumShouldMatch(1);
                        boolQueryBuilder.filter(innerBoolQueryBuilder);
                    } else {
                        boolQueryBuilder.filter(termQuery("refId", callCallLogListDTO.getDataId()));
                        boolQueryBuilder.filter(rangeQuery("refType").gte(codeCustomer).lte(codeCustomer));
                    }
                } else {
                    boolQueryBuilder.filter(termQuery("refId", callCallLogListDTO.getDataId()));
                    boolQueryBuilder.filter(rangeQuery("refType").gte(businessType).lte(businessType));
                }
            }
            Integer callSource = callCallLogListDTO.getCallSource();
            if (Objects.nonNull(callSource)) {
                boolQueryBuilder.filter(rangeQuery("callSource").gte(callSource).lte(callSource));
            }
            Integer type = callCallLogListDTO.getType();
            if (Objects.nonNull(type)) {
                boolQueryBuilder.filter(rangeQuery("type").gte(type).lte(type));
            }
            Integer result = callCallLogListDTO.getResult();
            if (Objects.nonNull(result)) {
                boolQueryBuilder.filter(rangeQuery("result").gte(result).lte(result));
            }
            if (Objects.nonNull(callCallLogListDTO.getFuzzySearch())) {
                BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
                innerBoolQueryBuilder.should(matchPhraseQuery("refName", callCallLogListDTO.getFuzzySearch()));
                innerBoolQueryBuilder.should(matchPhraseQuery("agentPhoneNum", callCallLogListDTO.getFuzzySearch()));
                innerBoolQueryBuilder.should(matchPhraseQuery("anotherPhoneNum", callCallLogListDTO.getFuzzySearch()));
                innerBoolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
                boolQueryBuilder.filter(innerBoolQueryBuilder);
            }
            RangeQueryBuilder durationQuery = rangeQuery("duration");
            if (Objects.nonNull(callCallLogListDTO.getDurationStart())) {
                durationQuery = rangeQuery("duration");
                durationQuery.gte(callCallLogListDTO.getDurationStart());
            }
            if (Objects.nonNull(callCallLogListDTO.getDurationEnd())) {
                if(durationQuery == null){
                    durationQuery = rangeQuery("duration");
                }
                durationQuery.lt(callCallLogListDTO.getDurationEnd());
            }
            if(durationQuery !=null){
                boolQueryBuilder.filter(durationQuery);
            }
            boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
            Boolean audioTranslated = callCallLogListDTO.getAudioTranslated();
            if (Objects.nonNull(audioTranslated) && audioTranslated) {
                // 不为空
                boolQueryBuilder.filter(boolQuery().mustNot(termQuery("recordContent","")));
                boolQueryBuilder.filter(existsQuery("recordContent"));
            } else if (Objects.nonNull(audioTranslated)) {
                BoolQueryBuilder boolQuery = boolQuery();
                boolQuery.should(boolQuery().filter(termQuery("recordContent", "")));
                boolQuery.should(boolQuery().mustNot(existsQuery("recordContent")));
                boolQuery.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
                boolQueryBuilder.filter(boolQuery);
            }
            IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG;
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            // 搜索条件
            sourceBuilder.query(boolQueryBuilder);
            //分页
            sourceBuilder.sort(new FieldSortBuilder("addTime").order(SortOrder.DESC));
            PageRequest pageRequest = EsUtil.setPage(sourceBuilder, callCallLogListDTO.getPage(), callCallLogListDTO.getPageSize());
            //设置查询路由
            SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
            searchRequest.source(sourceBuilder);
            XbbAggregatedPage<CallCenterCallLogEntity> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest,CallCenterCallLogEntity.class);
            if (esEntities == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            callLogEntityList = new ArrayList<>(esEntities.getContent());
            long count = esEntities.getTotalElements();
            pageHelper = new PageHelper(callCallLogListDTO.getPage(), callCallLogListDTO.getPageSize());
            pageHelper.setRowsCount((int)count);
        } catch (Exception e) {
            LOG.error("CallCenterCallLogServiceImpl.getCallLogList 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

        List<CallLogPojo> callLogPojos = new ArrayList<>();
        List<Object> customerIdIn = new ArrayList<>();
        List<Object> customerIdInNew = new ArrayList<>();
        List<Object> contactIdIn = new ArrayList<>();
        List<Object> contactIdInNew = new ArrayList<>();
        List<Object> clueIdIn = new ArrayList<>();
        List<Object> clueIdInNew = new ArrayList<>();

        for (CallCenterCallLogEntity callLogEntity : callLogEntityList) {
            Long refId = callLogEntity.getRefId();
            if(refId==null){
                continue;
            }
            CallLogPojo callLogPojo = new CallLogPojo();
            BeanUtil.copyProperties(callLogEntity, callLogPojo);
            callLogPojo.setUsername(callLogEntity.getUserName());
            // 当录音转文字的文本不为空时，为true，为了防止爬虫，清空转录文本
            if (StringUtil.isNotEmpty(callLogEntity.getRecordContent())) {
                callLogPojo.setTranslated(true);
                callLogPojo.setRecordContent(null);
            } else {
                callLogPojo.setTranslated(false);
            }
            if (Objects.equals(callLogEntity.getRefType(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())) {
                customerIdIn.add(callLogEntity.getRefId());
                customerIdInNew = new ArrayList<>(new HashSet(customerIdIn));
            } else if (Objects.equals(callLogEntity.getRefType(), XbbRefTypeEnum.CONTACT.getCode())) {
                contactIdIn.add(callLogEntity.getRefId());
                contactIdInNew = new ArrayList<>(new HashSet(contactIdIn));
            } else if (Objects.equals(callLogEntity.getRefType(), XbbRefTypeEnum.CLUE.getCode())) {
                clueIdIn.add(callLogEntity.getRefId());
                clueIdInNew = new ArrayList<>(new HashSet(clueIdIn));
            }
            callLogPojos.add(callLogPojo);
        }
        callLogEach(callCallLogListDTO, callLogPojos, customerIdInNew, contactIdInNew, clueIdInNew);

        callLogListVO.setCallLogList(callLogPojos);
        callLogListVO.setPageHelper(pageHelper);
        callLogListVO.setTotalElements(pageHelper.getRowsCount());
        // youli.chen 号码段隐藏是针对整个公司
        XbbResponse<CallCenterConfigVO> configResponse = callCenterConfigService.getByCorpId(callCallLogListDTO.getCorpid(), callCallLogListDTO.getModuleType());
        CallCenterConfigVO callCenterConfigVO = configResponse.getResult();
        Boolean showPhone = true;
        if (callCenterConfigVO == null) {
            callCenterConfigVO = new CallCenterConfigVO();
            callCenterConfigVO.setIsShowPhone(1);
        }
        showPhone = callCenterConfigVO.getIsShowPhone().equals(1) ? true : false;
        callLogListVO.setShowPhone(showPhone);

        return callLogListVO;
    }

    /**
     * 跳转
     */
    private void callLogEach(CallCallLogListDTO callCallLogListDTO, List<CallLogPojo> callLogPojos, List<Object> customerIdIn, List<Object> contactIdIn, List<Object> clueIdInNew) throws XbbException {
        // 客户
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        //解析查询条件
        boolQueryBuilder.filter(termQuery("corpid.keyword", callCallLogListDTO.getCorpid()));
        boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termsQuery("dataId",customerIdIn));
        // 限制返回值
        List<String> field = Arrays.asList(FieldTypeEnum.DATAID.getAlias(), StringConstant.JSON_DATA, ParameterConstant.FORMID, ParameterConstant.MENUID, ParameterConstant.APPID);

        IndexTypeEnum indexTypeEnum = indexTypeModel.getCustomerIndex(callCallLogListDTO.getCorpid(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());

        List<PaasFormDataEntityExt> customerESList = esHelper.findByScroll(indexTypeEnum,boolQueryBuilder,PaasFormDataEntityExt.class,field);

        // 联系人
        BoolQueryBuilder contactBuilder = boolQuery();
        //解析查询条件
        contactBuilder.filter(termQuery("corpid.keyword", callCallLogListDTO.getCorpid()));
        contactBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        contactBuilder.filter(termsQuery("dataId",contactIdIn));
        // 限制返回值
        List<String> fieldList = Arrays.asList(FieldTypeEnum.DATAID.getAlias(), StringConstant.JSON_DATA, ParameterConstant.FORMID, ParameterConstant.MENUID, ParameterConstant.APPID);
        List<PaasFormDataEntityExt> contactESList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CONTACT,contactBuilder,PaasFormDataEntityExt.class,fieldList);

        // 线索
        BoolQueryBuilder clueBuilder = boolQuery();
        //解析查询条件
        clueBuilder.filter(termQuery("corpid.keyword", callCallLogListDTO.getCorpid()));
        clueBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        clueBuilder.filter(termsQuery("dataId",clueIdInNew));
        // 限制返回值
        List<String> clueFieldList = Arrays.asList(FieldTypeEnum.DATAID.getAlias(), StringConstant.JSON_DATA, ParameterConstant.FORMID, ParameterConstant.MENUID, ParameterConstant.APPID);
        List<PaasFormDataEntityExt> clueESList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CLUE, clueBuilder, PaasFormDataEntityExt.class, clueFieldList);

        // 当前登陆人有权限的客户表单模版
        List<PaasFormEntityExt> paasFormEntityExtList = paasFormService.getEnableCustomerFormListDistributor(callCallLogListDTO.getLoginUser(), 0);
        if(paasFormEntityExtList.isEmpty()){
            throw new XbbException(ClueErrorCodeEnum.API_ERROR_1110013);
        }

        CallLogExplainPojo customerEntityExplain = new CallLogExplainPojo();
        // 客户的第一个表单模版
        PaasFormEntityExt entityExt = paasFormEntityExtList.get(0);

        customerEntityExplain.setMenuId(entityExt.getMenuId());
        customerEntityExplain.setFormId(entityExt.getId());
        customerEntityExplain.setAppId(entityExt.getAppId());

        customerEntityExplain.setSaasMark(SaasMarkEnum.SAAS.getCode());
        customerEntityExplain.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
        customerEntityExplain.setSubBusinessType(XbbRefTypeEnum.CUSTOMER.getCode());

        // 陌生号码默认插入客户的第一个表单模版
        for(CallLogPojo callLogPojo : callLogPojos){
            Integer refType = callLogPojo.getRefType();
            Long refId = callLogPojo.getRefId();
            if (Objects.equals(refType, XbbRefTypeEnum.UNKNOWN.getCode()) || Objects.equals(refId, 0L)) {
                callLogPojo.setEntity(customerEntityExplain);
            }
        }
        callLogPojos.forEach(callLogPojo -> {
            Integer refType = callLogPojo.getRefType();
            if (Objects.equals(refType, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())) {
                for (PaasFormDataEntityExt paasFormDataEsEntity : customerESList) {
                    if (Objects.equals(paasFormDataEsEntity.getDataId(), callLogPojo.getRefId())) {
                        CallLogExplainPojo entity = new CallLogExplainPojo();
                        BeanUtil.copyProperties(paasFormDataEsEntity, entity);
                        entity.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                        entity.setSaasMark(SaasMarkEnum.SAAS.getCode());
                        callLogPojo.setEntity(entity);
                    }
                }
            }
        });

        callLogPojos.forEach(callLogPojo -> {
            Integer refType = callLogPojo.getRefType();
            if (Objects.equals(refType, XbbRefTypeEnum.CONTACT.getCode())) {
                for (PaasFormDataEntityExt paasFormDataEsEntity : contactESList) {
                    if (Objects.equals(paasFormDataEsEntity.getDataId(), callLogPojo.getRefId())) {
                        CallLogExplainPojo entity = new CallLogExplainPojo();
                        BeanUtil.copyProperties(paasFormDataEsEntity, entity);
                        entity.setBusinessType(XbbRefTypeEnum.CONTACT.getCode());
                        entity.setSaasMark(SaasMarkEnum.SAAS.getCode());
                        callLogPojo.setEntity(entity);
                    }
                }
            }
        });

        callLogPojos.forEach(callLogPojo -> {
            Integer refType = callLogPojo.getRefType();
            if (Objects.equals(refType, XbbRefTypeEnum.CLUE.getCode())) {
                for (PaasFormDataEntityExt paasFormDataEsEntity : clueESList) {
                    if (Objects.equals(paasFormDataEsEntity.getDataId(), callLogPojo.getRefId())) {
                        CallLogExplainPojo entity = new CallLogExplainPojo();
                        BeanUtil.copyProperties(paasFormDataEsEntity, entity);
                        entity.setBusinessType(XbbRefTypeEnum.CLUE.getCode());
                        entity.setSaasMark(SaasMarkEnum.SAAS.getCode());
                        callLogPojo.setEntity(entity);
                    }
                }
            }
        });
    }

    /**
     * 获取企业方面的未接来电
     *
     * @param callCallLogListDTO 通话记录请求参数
     * @param depId              部门id（管理员可以不传depId而看到全公司的未接来电）
     * @return CallLogListVO 封装的通话记录返回参数
     * @throws XbbException 业务异常
     * @author youli.chen
     * 创建时间：2019/2/18 下午7:43
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    private CallLogListVO getOrgMissedCallLogList(CallCallLogListDTO callCallLogListDTO, Long depId) throws XbbException {
        CallLogListVO callLogListVO = new CallLogListVO();
        String corpid = callCallLogListDTO.getCorpid();
        String apiKey = callCenterOrganizationService.getApiKey(corpid, callCallLogListDTO.getModuleType());
        Long teamId = null;
        if (depId != null) {
            CallCenterTeamEntity team = callCenterTeamService.getByXbbDepInfo(corpid, depId, callCallLogListDTO.getModuleType());
            if (team != null && StringUtil.isNotEmpty(team.getTeamId())) {
                teamId = Long.parseLong(team.getTeamId());
            } else {
                throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301060);
            }
        }
        if (callCallLogListDTO.getStartTime() == null) {
            callCallLogListDTO.setStartTime(DateUtil.getTodayInt() - TimeConstant.SECONDS_PER_MONTH +
                    TimeConstant.SECONDS_ALLOWANCE);
        }
        if (callCallLogListDTO.getEndTime() == null) {
            callCallLogListDTO.setEndTime(DateUtil.getTodayInt());
        }
        DuYanCallLogResponseParamVO duYanCallLogResponseParamVO = duYanHttpService.getOrgMissedCallLogList(apiKey,
                callCallLogListDTO.getPage(), callCallLogListDTO.getPageSize(),
                callCallLogListDTO.getStartTime() * 1000L,
                callCallLogListDTO.getEndTime() * 1000L, teamId);
        callLogListVO.setTotalPages(duYanCallLogResponseParamVO.getTotalPages());
        callLogListVO.setTotalElements(duYanCallLogResponseParamVO.getTotalElements());
        if (duYanCallLogResponseParamVO.getCallLogs() == null || duYanCallLogResponseParamVO.getCallLogs().size() == 0) {
            callLogListVO.setCallLogList(new ArrayList<>());
        } else {
            List<CallLogPojo> callLogs = new ArrayList<>();
            for (DuYanCallLogVO it : duYanCallLogResponseParamVO.getCallLogs()) {
                CallCenterFindRefDTO refDTO = callCenterCommonService.findRefByPhoneNum(corpid, it.getCaller());
                CallLogPojo callLogPojo = new CallLogPojo();
                callLogPojo.setCorpid(corpid);
                callLogPojo.setUserId(callCallLogListDTO.getUserId());
                callLogPojo.setModuleType(callCallLogListDTO.getModuleType());
                callLogPojo.setRefId(refDTO.getRefId());
                callLogPojo.setRefType(refDTO.getRefType());
                callLogPojo.setRefName(refDTO.getRefName());
                callLogPojo.setCallTime((int) (it.getCallTime() / 1000L));
                callLogPojo.setAnotherPhoneNum(it.getCaller());
                callLogs.add(callLogPojo);
            }
            callLogListVO.setCallLogList(callLogs);
            // 将这批未接来电存入本地通话记录
            List<CallCenterCallLogEntity> callLogEntity = new ArrayList<>();
            try {
                BeanUtil.copyPropertiesList(callLogs, callLogEntity, CallCenterCallLogEntity.class);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            syncMissedCallLogList(corpid, callCallLogListDTO.getUserId(), callLogEntity);
        }
        return callLogListVO;
    }

    /**
     * 设置通话记录的录音文件路径
     *
     * @param callCenterCallLogEntity 通话录音
     * @throws XbbException 业务异常
     * @author youli.chen
     * 创建时间：2019/2/18 下午7:43
     * 修改时间：
     * @version v1.0
     * @since v1.0
     */
    private void initRecordUrl(CallCenterCallLogEntity callCenterCallLogEntity) throws XbbException {
        if (Objects.equals(callCenterCallLogEntity.getResult(), CallLogResultEnum.SUCCESS.getCode())) {
            // 通话成功，尝试直接获取通话录音路径
            if (Objects.equals(callCenterCallLogEntity.getModuleType(), CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode())) {
                // 度言话务中心
                if (StringUtil.isNotEmpty(callCenterCallLogEntity.getCallUuid())) {
                    CallCenterOrgGetByCorpIdVO getByCorpIdVO = callCenterOrganizationService.getByCorpId(callCenterCallLogEntity.getCorpid(),
                            callCenterCallLogEntity.getModuleType());
                    if (getByCorpIdVO == null) {
                        throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301001);
                    }
                    if (getByCorpIdVO != null && StringUtil.isNotEmpty(getByCorpIdVO.getApikey())) {
                        // 再次确认企业是否注册
                        try {
                            String recordUrl = duYanHttpService.getRecordUrlStatic(getByCorpIdVO.getApikey(),
                                    getByCorpIdVO.getOrgId(), DateUtil.getDateString(callCenterCallLogEntity.getCallTime()),
                                    callCenterCallLogEntity.getCallUuid());
                            callCenterCallLogEntity.setRecordUrl(recordUrl);
                        } catch (XbbException e) {
                            LOG.error("公司（%s）的通话记录（%d）设置通话录音失败：%s", callCenterCallLogEntity.getCorpid(),
                                    callCenterCallLogEntity.getId(), e);
                            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301061);
                        }
                    }
                }
            }
        }
    }

    /**
     * 同步未接来电到本地通话记录
     *
     * @param callLogList 未接来电列表
     * @author 章华隽
     * 创建时间：2017/12/7 上午10:24
     * 修改时间：
     * @version 3.14.1
     * @since 3.14.1
     */
    private void syncMissedCallLogList(final String corpid, final String userId, final List<CallCenterCallLogEntity> callLogList) {
        // 短时间内重复请求不需要同步
        String syncMark = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_CALL_LOG_SYNC_MARK, corpid + StringConstant.COLON + userId);
        if (StringUtil.isNotEmpty(syncMark)) {
            return;
        }
        paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_CALL_LOG_SYNC_MARK, corpid + StringConstant.COLON + userId,
                "synced", RedisConstant.SHORT_DURATION);
        ThreadPoolHelper.getInstance().submitExecutorRunnable(callCenterThreadPool, new Runnable() {
            @Override
            public void run() {
                // 插入时需要校验该通话记录是否已经保存，当前效率较低，是否有优化空间？
                Map<String, Object> params = new HashMap<>(16);
                params.put("corpid", corpid);
                params.put("type", CallLogTypeEnum.INBOUND.getCode());
                params.put("endUpdateTime", DateUtil.getInt());
                params.put("start", 0);
                params.put("pageNum", 1);
                params.put("columns", "id");
                for (CallCenterCallLogEntity it : callLogList) {
                    params.put("anotherPhoneNum", it.getAnotherPhoneNum());
                    params.put("callTime", it.getCallTime());
                    List<CallCenterCallLogEntity> list = callCenterCallLogModel.findEntitys(params);
                    if (list.size() == 0) {
                        try {
                            callCenterCallLogModel.insert(it);
                        } catch (XbbException e) {
                            e.printStackTrace();
                            LOG.error("未接来电同步到本地失败", e);
                        }
                    }
                }
            }
        });
    }

    /**
     * 根据翻译结果得到对话内容队列
     *
     * @param startTime                      接通电话的时间
     * @param duYanTranscriptionItemPojoList 翻译结果内容
     * @return 对话内容队列
     * @author 章华隽
     * 创建时间：2018/3/12 下午5:50
     * 修改时间：
     * @version 3.19
     * @since 3.19
     */
    private List<RecordContentPojo> formatTranslateData2RecordContents(Integer startTime,
                                                                       List<DuYanTranscriptionItemPojo> duYanTranscriptionItemPojoList) {
        List<RecordContentPojo> recordContents = new ArrayList<>();
        for (DuYanTranscriptionItemPojo it : duYanTranscriptionItemPojoList) {
            String speaker;
            if (it.getChannelId() == null) {
                speaker = "0";
            } else {
                speaker = it.getChannelId().toString();
            }
            int seconds = 0;
            if (it.getBeginTime() != null) {
                seconds = (int) (it.getBeginTime() / 1000L);
            }
            recordContents.add(new RecordContentPojo(speaker, it.getText(), startTime + seconds));
        }
        return recordContents;
    }

    /**
     * 度言平台通话录音翻译
     *
     * @param callCenterCallLogEntity 需要翻译的通话记录
     * @param callAudioTranslateVO    转录的文本
     * @param corpid
     * @param logId
     * @return
     * @throws XbbException
     */
    private CallAudioTranslateVO duYanTelPlat(CallCenterCallLogEntity callCenterCallLogEntity,
                                              CallAudioTranslateVO callAudioTranslateVO, String corpid, Long logId) throws XbbException {
        // 度言平台翻译并非异步操作，直接提交任务
        String apiKey = callCenterOrganizationService.getApiKey(corpid, callCenterCallLogEntity.getModuleType());
        if (StringUtil.isEmpty(apiKey)) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301001);
        }
        DuYanTranscriptionResponseVO duYanTransVO = duYanHttpService.postCallTranscription(apiKey, callCenterCallLogEntity.getCallUuid());
        callCenterCallLogEntity.setTranslatePlatform(StringConstant.PLATFORM_DUYAN);
        if (Objects.equals(duYanTransVO.getStatus(), DuYanConstant.CALL_TRANSCRIPTION_STATUS_DONE)) {
            // 翻译完成
            String translateData;
            String recordContent;
            if (StringUtil.isEmpty(duYanTransVO.getContent())) {
                translateData = "";
                recordContent = "";
            } else {
                DuYanTranscriptionVO duYanTranscriptionVO = JSON.parseObject(duYanTransVO.getContent(), DuYanTranscriptionVO.class);
                translateData = JSON.toJSONString(duYanTranscriptionVO.getResult());
                List<RecordContentPojo> contentList = formatTranslateData2RecordContents(callCenterCallLogEntity.getCallTime()
                                + callCenterCallLogEntity.getRingTime(),
                        JSON.parseArray(translateData, DuYanTranscriptionItemPojo.class));
                recordContent = JSON.toJSONString(contentList);

            }
            callCenterCallLogEntity.setTranslateData(translateData);
            callCenterCallLogEntity.setRecordContent(recordContent);
            callCenterCallLogModel.update(callCenterCallLogEntity);
            callAudioTranslateVO.setTaskResult(StringConstant.SUCCESS);
            // 翻译成功
            List<RecordContentPojo> recordContents = JSON.parseArray(callCenterCallLogEntity.getRecordContent(), RecordContentPojo.class);
            callAudioTranslateVO.setRecordContents(recordContents);
            return callAudioTranslateVO;
        } else if (Objects.equals(duYanTransVO.getStatus(), DuYanConstant.CALL_TRANSCRIPTION_STATUS_TRANSCRIBING)) {
            // 翻译中
            callAudioTranslateVO.setTaskResult(StringConstant.WAITING);
            return callAudioTranslateVO;
        } else {
            // 未知状态，当前当作翻译错误处理
            LOG.error("[度言语音翻译]公司（%s）的通话记录（%s）翻译状态不明：%s", corpid, logId, duYanTransVO.getStatus());
            paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_CALL_LOG_TRANSLATE_STATUS,
                    corpid + StringConstant.COLON + logId, StringConstant.FAILED, RedisConstant.COMMON_DURATION);
            callCenterCallLogModel.update(callCenterCallLogEntity);
            callAudioTranslateVO.setTaskResult(StringConstant.FAILED);
            return callAudioTranslateVO;
        }
    }

    /**
     * 非度言平台通话录音翻译
     *
     * @param callCenterCallLogEntity 需要翻译的通话记录
     * @param callAudioTranslateVO    转录的文本
     * @param corpid
     * @param logId
     * @return
     * @throws XbbException
     */
    private CallAudioTranslateVO notDuYanTelPlat(CallCenterCallLogEntity callCenterCallLogEntity, CallAudioTranslateVO callAudioTranslateVO,
                                                 String corpid, Long logId, String telPlat) throws XbbException {
        // 讯飞的转译服务已经欠费，暂时采用阿里云转录的方法  2019.7.29
        final String platformFinal = telPlat.toLowerCase();
        final String recordUrl;
        String mp3Tail = ".mp3";
        if (Objects.equals(CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode(), callCenterCallLogEntity.getModuleType())) {
            String ogaTail = ".oga";
            // 度言平台的录音，将oga链接改为mp3
            recordUrl = callCenterCallLogEntity.getRecordUrl().replace(ogaTail, mp3Tail);
        } else {
            // 销帮帮呼叫中心的录音文件链接是MP3
            recordUrl = callCenterCallLogEntity.getRecordUrl();
        }
        if (!recordUrl.contains(mp3Tail)) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301062);
        }
        int time = audioFileService.getMp3TimeSeconds(recordUrl);
        int halfMinuteSeconds = 30;
        if (time < halfMinuteSeconds) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, "语音转写服务对半分钟以下的录音识别较差，请自行监听");
        }
        // TODO 章华隽 2018-01-23 当前测试阶段先不做语音转写的时间上限
        ThreadPoolHelper.getInstance().submitExecutorRunnable(callCenterThreadPool, new Runnable() {
            @Override
            public void run() {
                String fileName = recordUrl.substring(recordUrl.lastIndexOf("/") + 1, recordUrl.length());
                String savePath = File.separator + "acs" + File.separator + "upload" + File.separator + "mp3";
                audioFileService.checkDirExists(savePath);
                String filePath = savePath + File.separator + fileName;
                File file = new File(filePath);
                if (file.exists()) {
                    LOG.info("公司（%s）的通话记录（%d）的录音文件（%s）已经提前下载成功了", corpid, logId, filePath);
                } else {
                    // 文件还没下载到本地
                    LOG.warn("公司（%s）的通话记录（%d）的录音文件（%s）还没下载到本地", corpid, logId, filePath);
                    try {
                        filePath = audioFileService.downloadFromUrl(recordUrl, fileName, savePath);
                    } catch (Exception e) {
                        LOG.error("公司（%s）的录音（%s）的链接（%s）有问题，无法下载：%s", corpid, logId, recordUrl, e);

                        // 将"失败"状态写入Redis缓存
                        paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_CALL_LOG_TRANSLATE_STATUS,
                                corpid + StringConstant.COLON + logId, StringConstant.FAILED, RedisConstant.COMMON_DURATION);
                    }
                    LOG.info("公司（%s）的通话记录（%d）的录音文件（%s）下载到本地成功", corpid, logId, filePath);
                }
                if (StringUtil.isNotEmpty(filePath)) {
                    if (StringConstant.PLATFORM_XUN_FEI.equals(platformFinal)) {
                        try {
                            xunFeiAudioTranslatorService.translateLocalPhoneAudio(callCenterCallLogEntity, filePath);
                        } catch (XbbException e) {
                            e.printStackTrace();
                            callAudioTranslateVO.setTaskResult(StringConstant.FAILED);
                        }
                    } else {
                        try {
                            aliyunAudioTranslatorService.translateLocalPhoneAudio(callCenterCallLogEntity, filePath);
                        } catch (XbbException e) {
                            e.printStackTrace();
                            callAudioTranslateVO.setTaskResult(StringConstant.FAILED);
                        }
                    }
                }
            }
        });
        callAudioTranslateVO.setTaskResult(StringConstant.WAITING);
        return callAudioTranslateVO;
    }

    /**
     * 防封号规则
     * @param callCallLogSaveDTO 通话记录入参
     * @param callCenterConfigVO 呼叫配置
     */
    private void callBlockRule(CallCallLogSaveDTO callCallLogSaveDTO, CallCenterConfigVO callCenterConfigVO){
        String corpid = callCallLogSaveDTO.getCorpid();
        String ccId = callCallLogSaveDTO.getCcId();
        Integer callBlockInterval = callCenterConfigVO.getCallBlockInterval();
        Integer callBlockThirtyNum = callCenterConfigVO.getCallBlockThirtyNum();
        Integer callBlockDayNum = callCenterConfigVO.getCallBlockDayNum();
        Integer now = DateUtil.getInt();
        // 呼叫时间间隔
        if(!Objects.equals(callBlockInterval, BasicConstant.ZERO)){
            String intervalRedisKey = corpid + "_" + ccId + "_" + "interval";
            // lock == "原先设定的时间间隔"
            String lock = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_INTERVAL_LOCK, intervalRedisKey);
            if(StringUtil.isNotEmpty(lock) && callBlockInterval > StringUtil.toInt(lock)){
                // 呼叫时间间隔(生命周期)
                Long lockTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_INTERVAL_LOCK, intervalRedisKey);
                // 重新设置规则之后，大于原先设定值时，重置value值
                // 自定义时间间隔
                Integer interval = callBlockInterval - StringUtil.toInt(lock);
                Integer newTime = lockTime.intValue() + interval;
                paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_INTERVAL_LOCK, intervalRedisKey, callBlockInterval, newTime);
                // 更新的呼叫时间间隔倒计时
                Long newLockTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_INTERVAL_LOCK, intervalRedisKey);
                LOG.info("after save callLog update callBlockInterval time --------->>>>" + newLockTime);
            } else if(StringUtil.isNotEmpty(lock) && callBlockInterval <= StringUtil.toInt(lock)){
                // 缓存时间重置
                paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_INTERVAL_LOCK, intervalRedisKey, callBlockInterval, callBlockInterval);
                Long lockTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_INTERVAL_LOCK, intervalRedisKey);
                // 重置之前的缓存时间
                LOG.info("after save callLog reset callBlockInterval time --------->>>>" + lockTime);
            } else if(StringUtil.isEmpty(lock)){
                // 直接生成一个自定义生命周期的redis，下一次呼叫之前判断是否失效
                paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_INTERVAL_LOCK, intervalRedisKey, callBlockInterval, callBlockInterval);
                // 新生成的呼叫时间间隔倒计时
                Long lockTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_INTERVAL_LOCK, intervalRedisKey);
                LOG.info("after save callLog insert callBlockInterval time --------->>>>" + lockTime);
            }
        }
        // 30分钟最多拨打次数 离散型方案
        if(!Objects.equals(callBlockThirtyNum, BasicConstant.ZERO)){
            String thirtyRedisKey = corpid + "_" + ccId + "_" + "thirty";
            // 限制的总次数
            String lock = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_THIRTY_LOCK, thirtyRedisKey);

            String oldLock = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_OLD_THIRTY_LOCK, thirtyRedisKey);
            if(StringUtil.isEmpty(oldLock)){
                paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_OLD_THIRTY_LOCK, thirtyRedisKey, callBlockThirtyNum, RedisConstant.SHORTER_DURATION);
            }
            Boolean updateLock = (StringUtil.isNotEmpty(oldLock) && callBlockThirtyNum > StringUtil.toInt(oldLock)) ||
                    (StringUtil.isEmpty(oldLock) && StringUtil.isNotEmpty(lock) && callBlockThirtyNum > StringUtil.toInt(lock));

            Boolean resetLock = (StringUtil.isNotEmpty(oldLock) && callBlockThirtyNum <= StringUtil.toInt(oldLock)) ||
                    (StringUtil.isEmpty(oldLock) && StringUtil.isNotEmpty(lock) && callBlockThirtyNum <= StringUtil.toInt(lock));

            if(updateLock){
                Long lockTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_THIRTY_LOCK, thirtyRedisKey);
                // 重新设置规则之后，大于原先设定值时，重置value值，减法
                // 生命周期三十分钟，value值为自定义次数
                Integer thirtyNum = callBlockThirtyNum - StringUtil.toInt(lock);
                // 生命周期依然是上一个缓存的剩余时间
                paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_THIRTY_LOCK, thirtyRedisKey, thirtyNum, lockTime.intValue());
                // 更新的30分钟最多拨打次数倒计时
                lockTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_THIRTY_LOCK, thirtyRedisKey);
                LOG.info("after save callLog update callBlockThirtyNum time --------->>>>" + lockTime);

                // 冗余缓存之前的拨打次数 lock = 上一次设定的次数
                paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_OLD_THIRTY_LOCK, thirtyRedisKey, lock, lockTime.intValue());
                lockTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_OLD_THIRTY_LOCK, thirtyRedisKey);
                LOG.info("after save callLog save old callBlockThirtyNum time --------->>>>" + lockTime);

            } else if(resetLock){
                // 重置生命周期
                paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_THIRTY_LOCK, thirtyRedisKey, callBlockThirtyNum, RedisConstant.SHORTER_DURATION);
                // 重置呼叫时间间隔倒计时
                Long lockTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_THIRTY_LOCK, thirtyRedisKey);
                LOG.info("after save callLog reset callBlockThirtyNum time --------->>>>" + lockTime);
            } else if(StringUtil.isEmpty(lock)){
                // 直接生成一个30分钟的redis，下一次呼叫之前判断是否失效并value值是否超出
                paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_THIRTY_LOCK, thirtyRedisKey, callBlockThirtyNum, RedisConstant.SHORTER_DURATION);
                // 新生成的呼叫时间间隔倒计时
                Long lockTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_THIRTY_LOCK, thirtyRedisKey);
                LOG.info("after save callLog insert callBlockThirtyNum time --------->>>>" + lockTime);
            }

            // 进行自增
            Long lockTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_THIRTY_LOCK, thirtyRedisKey);
            paasRedisHelper.getIncrNum(CallCenterConstant.REDIS_KEY_THIRTY_INCR_NUM_LOCK, thirtyRedisKey, lockTime.intValue(), 1, 1);
            LOG.info("after save callLog update callBlockThirtyNum+++1 time --------->>>>" + lockTime);
        }
        // 1天最多拨打次数 自然天计算
        if(!Objects.equals(callBlockDayNum, BasicConstant.ZERO)){
            Integer redisDayLive = DateUtil.getTodayInt() + RedisConstant.LONG_DURATION - now;
            String dayRedisKey = corpid + "_" + ccId + "_" + "day";
            String lock = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_DAY_LOCK, dayRedisKey);

            String oldLock = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_OLD_DAY_LOCK, dayRedisKey);
            if(StringUtil.isEmpty(oldLock)){
                paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_OLD_DAY_LOCK, dayRedisKey, callBlockDayNum, redisDayLive);
            }
            Boolean updateLock = (StringUtil.isNotEmpty(oldLock) && callBlockDayNum > StringUtil.toInt(oldLock)) ||
                    (StringUtil.isEmpty(oldLock) && StringUtil.isNotEmpty(lock) && callBlockDayNum > StringUtil.toInt(lock));

            Boolean resetLock = (StringUtil.isNotEmpty(oldLock) && callBlockDayNum <= StringUtil.toInt(oldLock)) ||
                    (StringUtil.isEmpty(oldLock) && StringUtil.isNotEmpty(lock) && callBlockDayNum <= StringUtil.toInt(lock));

            if(updateLock){
                // 重新设置规则之后，大于原先设定值时，重置value值，减法
                // 生命周期一个自然天，value值为自定义次数
                Integer dayNum = callBlockDayNum - StringUtil.toInt(lock);
                paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_DAY_LOCK, dayRedisKey, dayNum, redisDayLive);
                // 更新的一天最多拨打次数倒计时
                Long lockTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_DAY_LOCK, dayRedisKey);
                LOG.info("after save callLog update callBlockDayNum time --------->>>>" + lockTime);

                // 冗余缓存之前的拨打次数 lock = 上一次设定的次数
                paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_OLD_DAY_LOCK, dayRedisKey, lock, lockTime.intValue());
                lockTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_OLD_DAY_LOCK, dayRedisKey);
                LOG.info("after save callLog save old callBlockDayNum time --------->>>>" + lockTime);

            } else if(resetLock){
                // 重置生命周期
                paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_DAY_LOCK, dayRedisKey, callBlockDayNum, redisDayLive);
                // 重置呼叫时间间隔倒计时
                Long lockTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_DAY_LOCK, dayRedisKey);
                LOG.info("after save callLog reset callBlockDayNum time --------->>>>" + lockTime);
            } else if(StringUtil.isEmpty(lock)){
                // 直接生成一个自然天生命周期的redis，下一次呼叫之前判断是否失效并value值是否超出
                paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_DAY_LOCK, dayRedisKey, callBlockDayNum, redisDayLive);
                // 新生成的呼叫时间间隔倒计时
                Long lockTime = paasRedisHelper.getExpire(CallCenterConstant.REDIS_KEY_DAY_LOCK, dayRedisKey);
                LOG.info("after save callLog insert callBlockDayNum time --------->>>>" + lockTime);
            }
            // 进行自增
            paasRedisHelper.getIncrNum(CallCenterConstant.REDIS_KEY_DAY_INCR_NUM_LOCK, dayRedisKey, redisDayLive, 1, 1);
            LOG.info("after save callLog update callBlockDayNum+++1 time --------->>>>" + redisDayLive);
        }
    }

    /**
     * 初始化相关参数自动上传通话记录
     *
     * @param callRecordConfigDTO
     * @author lijiangren
     * @date 2021-07-07 13 55
     * @since
     * @version
     */
    @Override
    public CallRecordConfigVO getAutoUploadConfig(CallRecordConfigDTO callRecordConfigDTO) throws XbbException{
        CallRecordConfigVO callRecordConfigVO = new CallRecordConfigVO();
        if (!Objects.isNull(callRecordConfigDTO)) {
            callRecordConfigVO.setAutoRecordEnable(true);
            callRecordConfigVO.setAutoRecordFileNameType(BasicConstant.ONE);
            callRecordConfigVO.setAutoUploadLogEnable(true);
            callRecordConfigVO.setAutoUploadLogUrl(proBaseConfig.getProjectDingtalkUrl() + CallCenterCallBackConstant.CALL_BACK_URL);
            callRecordConfigVO.setAutoUploadEnable(true);
            callRecordConfigVO.setAutoUploadType(Constant.ONE);
            callRecordConfigVO.setAutoUploadUrl("");
            callRecordConfigVO.setAccessKeyId(proBaseConfig.getCallCenterAccessKeyId());
            callRecordConfigVO.setAccessKeySecret(proBaseConfig.getCallCenterAccessKeySecret());
            callRecordConfigVO.setBucketName(proBaseConfig.getCallCenterBucketName());
            callRecordConfigVO.setEndPoint(proBaseConfig.getCallCenterEndpoint());
            callRecordConfigVO.setPid(callRecordConfigDTO.getCorpid());
            callRecordConfigVO.setUserWid(callRecordConfigDTO.getUserId());
            callRecordConfigVO.setAutoUploadLogType(Constant.ONE);
            callRecordConfigVO.setTxCosPath(proBaseConfig.getCallCenterBucketName());
        }
        return callRecordConfigVO;
    }

    @Override
    public List<AliyunCallCenterPojo> listSyncCallRecord(AliyunListSyncCallRecordDTO recordDTO) throws XbbException {
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        List<CallCenterCallLogEntity> callLogEntityList;
        try {
            IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG;
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
            boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, recordDTO.getCorpid()));
            boolQueryBuilder.filter(termQuery("instanceId.keyword", recordDTO.getInstanceId()));
            boolQueryBuilder.filter(termQuery("isSynced", false));
            boolQueryBuilder.filter(termQuery("del", 0));
            boolQueryBuilder.mustNot(existsQuery("result"));
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            sourceBuilder.sort(new FieldSortBuilder("addTime").order(SortOrder.DESC));
            sourceBuilder.query(boolQueryBuilder);
            PageRequest pageRequest = EsUtil.setPage(sourceBuilder, recordDTO.getPageNumber(), recordDTO.getPageSize());
            //设置查询路由
            SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
            searchRequest.source(sourceBuilder);
            XbbAggregatedPage<CallCenterCallLogEntity> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, CallCenterCallLogEntity.class);
            if (esEntities == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            callLogEntityList = new ArrayList<>(esEntities.getContent());
        } catch (Exception e) {
            LOG.error("CallCenterCallLogServiceImpl.getCallLogList 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return callLogEntityList.stream().map(this::entityToPojo).collect(Collectors.toList());
    }

    @Override
    public List<AliyunCallCenterPojo> listUnsyncCallRecord(AliyunListUnSyncCallRecordDTO recordDTO) throws XbbException {
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        List<CallCenterCallLogEntity> callLogEntityList;
        try {
            IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG;
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
            boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, recordDTO.getCorpid()));
            boolQueryBuilder.filter(termQuery("instanceId.keyword", recordDTO.getInstanceId()));
            boolQueryBuilder.filter(termQuery("isSynced", true));
            boolQueryBuilder.filter(termQuery("del", 0));
            int code = AliyunCallCenterResultEnum.SUCCESS.getCode();
            boolQueryBuilder.filter(rangeQuery("result").gte(code).lte(code));
            boolQueryBuilder.mustNot(existsQuery("recordUrl"));
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            sourceBuilder.sort(new FieldSortBuilder("addTime").order(SortOrder.DESC));
            sourceBuilder.query(boolQueryBuilder);
            PageRequest pageRequest = EsUtil.setPage(sourceBuilder, recordDTO.getPageNumber(), recordDTO.getPageSize());
            //设置查询路由
            SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
            searchRequest.source(sourceBuilder);
            XbbAggregatedPage<CallCenterCallLogEntity> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, CallCenterCallLogEntity.class);
            if (esEntities == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            callLogEntityList = new ArrayList<>(esEntities.getContent());
        } catch (Exception e) {
            LOG.error("CallCenterCallLogServiceImpl.getCallLogList 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return callLogEntityList.stream().map(this::entityToPojo).collect(Collectors.toList());
    }

    @Override
    public Integer batchUpdateAliyunCallCenter(AliyunBatchUpdateDTO updateDTO) throws XbbException {
        String corpid = updateDTO.getCorpid();
        List<AliyunCallCenterModelDTO> modelDTOList = updateDTO.getModelDTOList();
        if (CollectionUtils.isEmpty(modelDTOList)) {
            return 0;
        }
        List<String> callIdList = modelDTOList.stream().map(AliyunCallCenterModelDTO::getCallId).filter(StringUtil::isNotEmpty).collect(Collectors.toList());
        // 根据通话ID查询通话记录
        Map<String, Object> param = new HashMap<>(3);
        param.put("corpid", corpid);
        param.put("callIdIn", callIdList);
        param.put("del", DelEnum.NORMAL.getDel());
        List<CallCenterCallLogEntity> centerCallLogEntityList = callCenterCallLogModel.findEntitys(param);
        if (CollectionUtils.isEmpty(centerCallLogEntityList)) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301088);
        }
        Map<String, Long> callIdMap = new HashMap<>();
        for (CallCenterCallLogEntity callLogEntity : centerCallLogEntityList) {
            // 已经同步过的通话记录跳过
            if (callLogEntity.getIsSynced()) {
                continue;
            }
            if (!callIdMap.containsKey(callLogEntity.getCallId())) {
                callIdMap.put(callLogEntity.getCallId(), callLogEntity.getId());
            }
        }


        List<String> anotherPhoneNumLsit = modelDTOList.stream()
                .map(dto -> Objects.nonNull(dto.getType()) && dto.getType().equals(0) ? dto.getAgentPhoneNum() : dto.getAnotherPhoneNum())
                .filter(StringUtil::isNotEmpty).collect(Collectors.toList());
        // 根据号码集合查询客户
        List<CustomerEntityExt> customerEntityExtList = customerModel.listByInPhone(corpid, anotherPhoneNumLsit, true);
        Map<String, CustomerEntityExt> customerEntityMap = new HashMap<>(customerEntityExtList.size());
        if (CollectionUtils.isNotEmpty(customerEntityExtList)) {
            for (CustomerEntityExt entityExt : customerEntityExtList) {
                List<String> phoneNumberList = this.getPhoneNumber(entityExt.getData(), CustomerManagementEnum.PHONE.getAttr());
                if (CollectionsUtil.isNotEmpty(phoneNumberList)) {
                    for (String phoneNumber : phoneNumberList) {
                        customerEntityMap.put(phoneNumber, entityExt);
                    }
                }
            }
        }

        // 按手机号查询联系人
        List<ContactEntityExt> contactEntityExtList = contactModel.listByInPhone(corpid, anotherPhoneNumLsit);
        Map<String, ContactEntityExt> contactEntityMap = new HashMap<>(contactEntityExtList.size());
        if (CollectionUtils.isNotEmpty(contactEntityExtList)) {
            for (ContactEntityExt entityExt : contactEntityExtList) {
                List<String> phoneNumberList = this.getPhoneNumber(entityExt.getData(), ContactEnum.PHONE.getAttr());
                if (CollectionsUtil.isNotEmpty(phoneNumberList)) {
                    for (String phoneNumber : phoneNumberList) {
                        contactEntityMap.put(phoneNumber, entityExt);
                    }
                }
            }
        }
        // 按手机号查询线索
        List<ClueEntityExt> clueEntityExtList = clueModel.listByInPhone(corpid, anotherPhoneNumLsit,true);
        Map<String, ClueEntityExt> clueEntityMap = new HashMap<>(clueEntityExtList.size());
        if (CollectionUtils.isNotEmpty(clueEntityExtList)) {
            for (ClueEntityExt entityExt : clueEntityExtList) {
                List<String> phoneNumberList = this.getPhoneNumber(entityExt.getData(), ClueEnum.PHONE.getAttr());
                if (CollectionsUtil.isNotEmpty(phoneNumberList)) {
                    for (String phoneNumber : phoneNumberList) {
                        clueEntityMap.put(phoneNumber, entityExt);
                    }
                }
            }
        }
        List<CallCenterCallLogEntity> list = new ArrayList<>(modelDTOList.size());
        for (AliyunCallCenterModelDTO modelDTO : modelDTOList) {
            String callId = modelDTO.getCallId();
            if (StringUtil.isEmpty(callId) || Objects.isNull(callIdMap.get(callId))) {
                continue;
            }
            Long callLogId = callIdMap.get(callId);
            // 将ID存起来
            CallCenterCallLogEntity callCenterCallLogEntity = modelToEntity(modelDTO);
            callCenterCallLogEntity.setUserName(modelDTO.getCallUserNames());
            callCenterCallLogEntity.setUserId(modelDTO.getCallUserIds());
            callCenterCallLogEntity.setIsSynced(true);
            callCenterCallLogEntity.setId(callLogId);
            if(Objects.nonNull(modelDTO.getAddTime())){
                callCenterCallLogEntity.setAddTime(DateUtil.getInt(modelDTO.getAddTime()));
            }
            // 客户号码
            String anotherPhoneNum = Objects.nonNull(modelDTO.getType()) && modelDTO.getType().equals(0) ? modelDTO.getAgentPhoneNum() : modelDTO.getAnotherPhoneNum() ;

            if (customerEntityMap.containsKey(anotherPhoneNum)) {
                CustomerEntityExt cusEntityExt = customerEntityMap.get(anotherPhoneNum);
                // 兼容，防止并发，通话记录重新查询
                callCenterCallLogEntity.setRefId(cusEntityExt.getId());
                callCenterCallLogEntity.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(cusEntityExt.getData(), CustomerManagementEnum.NAME.getAttr(), ""));
                callCenterCallLogEntity.setRefType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
            } else if (contactEntityMap.containsKey(anotherPhoneNum)) {
                ContactEntityExt contactEntityExt = contactEntityMap.get(anotherPhoneNum);
                callCenterCallLogEntity.setRefId(contactEntityExt.getId());
                callCenterCallLogEntity.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(contactEntityExt.getData(), ContactEnum.NAME.getAttr(), ""));
                callCenterCallLogEntity.setRefType(XbbRefTypeEnum.CONTACT.getCode());
            } else if (clueEntityMap.containsKey(anotherPhoneNum)) {
                ClueEntityExt clueEntityExt = clueEntityMap.get(anotherPhoneNum);
                callCenterCallLogEntity.setRefId(clueEntityExt.getId());
                callCenterCallLogEntity.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(clueEntityExt.getData(), ClueEnum.COMPANY_NAME.getAttr(), ""));
                callCenterCallLogEntity.setRefType(XbbRefTypeEnum.CLUE.getCode());
            } else {
                callCenterCallLogEntity.setRefId(0L);
                callCenterCallLogEntity.setRefName("--");
                callCenterCallLogEntity.setRefType(CallCenterTypeEnum.UNKNOWN.getCode());
            }
            list.add(callCenterCallLogEntity);
        }
        Integer res = callCenterCallLogModel.batchUpdateAliyunCallCenter(corpid, list);
        saveCommunicate(list,updateDTO);
        return res;
    }

    /**
     * 将Model转换为Entity
     *
     * @param modelDTO Model
     * @return Entity
     */
    private CallCenterCallLogEntity modelToEntity(AliyunCallCenterModelDTO modelDTO) {
        CallCenterCallLogEntity callCenterCallLogEntity = new CallCenterCallLogEntity();
        BeanUtils.copyProperties(modelDTO, callCenterCallLogEntity);
        Long contactTime = modelDTO.getContactTime();
        if (Objects.nonNull(contactTime)) {
            callCenterCallLogEntity.setCallTime(DateUtil.getInt(contactTime));
        }
        Long callDuration = modelDTO.getCallDuration();
        if (Objects.nonNull(callDuration)) {
            callCenterCallLogEntity.setDuration(Integer.parseInt(callDuration.toString()));
        }
        Long callRingTime = modelDTO.getCallRingTime();
        if (Objects.nonNull(callRingTime)) {
            callCenterCallLogEntity.setRingTime(Integer.parseInt(callRingTime.toString()));
        }
        callCenterCallLogEntity.setIsSynced(false);
        callCenterCallLogEntity.setCallSource(CallCenterCallLogCallSourceEnum.ALIYUN_CALL_CENTER.getCode());
        int now = DateUtil.getInt();
        if (Objects.nonNull(modelDTO.getAddTime())) {
            callCenterCallLogEntity.setAddTime(DateUtil.getInt(modelDTO.getAddTime()));
        } else {
            callCenterCallLogEntity.setAddTime(now);
        }
        callCenterCallLogEntity.setUpdateTime(now);
        return callCenterCallLogEntity;
    }


    /**
     * 获取通话记录的基本参数封装
     *
     * @param aliyunCallCenterListDTO 基本请求参数
     * @return CallLogListVO 封装的通话记录
     */
    private AliyunCallcenterListVO aliyunCallCenterRecordList(AliyunCallCenterListDTO aliyunCallCenterListDTO) throws XbbException {
        PageHelper pageHelper;
        List<CallCenterCallLogEntity> callLogEntityList;
        try {
            // 获取云呼通话记录的es查询条件
            BoolQueryBuilder queryParam = this.getAliyunCallCenterRecordEsQueryParam(aliyunCallCenterListDTO);
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            sourceBuilder.query(queryParam);
            // 根据排序字段进行排序
            if(StringUtils.isNotBlank(aliyunCallCenterListDTO.getSortField()) && StringUtils.isNotBlank(aliyunCallCenterListDTO.getSort())){
                String sortField = getSortField(aliyunCallCenterListDTO.getSortField());
                SortOrder sort = StringUtils.equalsIgnoreCase(aliyunCallCenterListDTO.getSort(), SortOrder.DESC.toString()) ? SortOrder.DESC : SortOrder.ASC;
                sourceBuilder.sort(new FieldSortBuilder(sortField).order(sort));
            } else if(StringUtils.isNotBlank(aliyunCallCenterListDTO.getSort())) {
                SortOrder sort = StringUtils.equalsIgnoreCase(aliyunCallCenterListDTO.getSort(), SortOrder.DESC.toString()) ? SortOrder.DESC : SortOrder.ASC;
                sourceBuilder.sort(new FieldSortBuilder("addTime").order(sort));
            } else {
                sourceBuilder.sort(new FieldSortBuilder("addTime").order(SortOrder.DESC));
            }
            // 分页信息
            PageRequest pageRequest = EsUtil.setPage(sourceBuilder, aliyunCallCenterListDTO.getPage(), aliyunCallCenterListDTO.getPageSize());
            //设置查询路由
            SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG.getIndex());
            searchRequest.source(sourceBuilder);
            XbbAggregatedPage<CallCenterCallLogEntity> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, CallCenterCallLogEntity.class);
            if (esEntities == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            callLogEntityList = new ArrayList<>(esEntities.getContent());
            long count = esEntities.getTotalElements();
            pageHelper = new PageHelper(aliyunCallCenterListDTO.getPage(), aliyunCallCenterListDTO.getPageSize());
            pageHelper.setRowsCount((int) count);
        } catch (Exception e) {
            LOG.error("CallCenterCallLogServiceImpl.aliyunCallCenterRecordList 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        List<AliyunCallCenterPojo> aliyunCallCenterPojos = callLogEntityList.stream().map(this::entityToPojo).collect(Collectors.toList());
        AliyunCallcenterListVO callCenterListVO = new AliyunCallcenterListVO();
        // 获取号码可见权限信息
        this.getNumberVisibleAuths(aliyunCallCenterPojos, aliyunCallCenterListDTO);
        callCenterListVO.setAliyunCallCenterPojos(aliyunCallCenterPojos);
        callCenterListVO.setPageHelper(pageHelper);
        callCenterListVO.setTotalElements(pageHelper.getRowsCount());
        callCenterListVO.setTotalPages(pageHelper.getPageTotal());
        return callCenterListVO;
    }

    @Override
    public Boolean getNumberVisibleh(String anotherPhoneNum, BaseDTO baseDTO) throws XbbException {
        // 是否可见
        boolean visible = true;
        if(anotherPhoneNum==null){
            return visible;
        }
        String corpid = baseDTO.getCorpid();
        // 查询表单信息
        PaasFormDataEntityExt paasFormDataEntityExt = null;
        // 根据公司ID和电话查询线索
        CustomerEntityExt cusEntityExt = null;
        // 联系人
        ContactEntityExt contactEntityExt = null;
        // 线索
        ClueEntityExt clueEntityExt = null;
        cusEntityExt = customerModel.getByPhoneIncloudRecycled(corpid, anotherPhoneNum);
        if(cusEntityExt!=null){
            paasFormDataEntityExt = cusEntityExt;
            paasFormDataEntityExt.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
        }else if(cusEntityExt==null){
            // 联系人
            contactEntityExt = contactModel.getByPhone(corpid, anotherPhoneNum);
            if(contactEntityExt!=null){
                paasFormDataEntityExt = contactEntityExt;
                paasFormDataEntityExt.setBusinessType(XbbRefTypeEnum.CONTACT.getCode());
            }
        }else {
            // 线索
            clueEntityExt = clueModel.getByPhoneIncloudRecycled(corpid, anotherPhoneNum);
            if(clueEntityExt!=null){
                paasFormDataEntityExt = clueEntityExt;
                paasFormDataEntityExt.setBusinessType(XbbRefTypeEnum.CLUE.getCode());
            }
        }
        if(paasFormDataEntityExt==null){
            return visible;
        }
        Integer businessType = paasFormDataEntityExt.getBusinessType();
        Long formId = paasFormDataEntityExt.getFormId();
        PaasFormEntityExt paasFormEntityExt = paasFormModel.getByKey(paasFormDataEntityExt.getFormId(), corpid);
        // 查询表单解释
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(paasFormEntityExt.getId(), corpid);
        if (Objects.isNull(paasFormExplainEntity)) {
            return visible;
        }
        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        Integer saasMark = paasFormExplainEntity.getSaasMark();
        // 不为空校验
        if (paasFormDataEntityExt == null) {
            return visible;
        }
        // 不为逻辑删除校验
        if (Objects.equals(paasFormDataEntityExt.getDel(),DelEnum.DELETE.getDel())) {
            return visible;
        }
        // 审批校验
        if (FlowStatusEnum.inApproval(paasFormDataEntityExt.getFlowStatus()) ) {
            return visible;
        }
        // 去获取表单模板中的信息
        HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
        BeanUtil.copyProperties(baseDTO, handlerExplainDTO, false);
        handlerExplainDTO.setCreatorId(paasFormDataEntityExt.getCreatorId());
        UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
        BeanUtil.copyProperties(baseDTO, userAndDepartmentGetDTO);
        userAndDepartmentGetDTO.setExplainList(explainList);
        Map<String, UserEntity> userMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        handlerExplainDTO.setExplainList(explainList);
        // 获取协同人和负责人
        paasFormHelp.getOwnerIdAndCoUserId(handlerExplainDTO, saasMark, businessType, businessType, paasFormDataEntityExt, userMap);
        handlerExplainDTO.setPaasFormEntityExt(paasFormEntityExt);
        handlerExplainDTO.setFormData(paasFormDataEntityExt.getData());
        // 获取表单解释
        HandlerExplainVO handlerExplainVO = formDataDetailFormExplainHandleName.handleExplain(handlerExplainDTO);
        List<FieldAttrEntity> headList = handlerExplainVO.getHeadList();
        // 将表单解释转为MAP key -> 字段名 value -> 为字段解释
        Map<String, FieldAttrEntity> attrEntityMap = headList.stream().collect(Collectors.toMap(FieldAttrEntity::getAttr, fieldAttrEntity -> fieldAttrEntity));
        SubFormPoJo subForm = null;
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        switch (xbbRefTypeEnum){
            case CUSTOMER_MANAGEMENT:
                if(attrEntityMap.containsKey(CustomerManagementEnum.PHONE.getAttr())){
                    // 客户
                    FieldAttrEntity fieldAttrEntity = attrEntityMap.get(CustomerManagementEnum.PHONE.getAttr());
                    subForm = fieldAttrEntity.getSubForm();
                }
                break;
            case CONTACT:
                // 联系人
                if(attrEntityMap.containsKey(ContactEnum.PHONE.getAttr())){
                    // 联系人
                    FieldAttrEntity fieldAttrEntity = attrEntityMap.get(ContactEnum.PHONE.getAttr());
                    subForm = fieldAttrEntity.getSubForm();
                }
                break;
            case CLUE:
                // 联系人
                if(attrEntityMap.containsKey(ClueEnum.PHONE.getAttr())){
                    // 销售线索
                    FieldAttrEntity fieldAttrEntity = attrEntityMap.get(ClueEnum.PHONE.getAttr());
                    subForm = fieldAttrEntity.getSubForm();
                }
                break;
            default:
                return visible;
        }

        if (Objects.nonNull(subForm) && CollectionUtils.isNotEmpty(subForm.getItems())){
            FieldAttrEntity attrEntity = subForm.getItems().stream().filter(item -> "text_2".equals(item.getAttr())).findAny().orElse(null);
            visible = Objects.nonNull(attrEntity) && attrEntity.getVisible().equals(1);
        }
        return visible;
    }

    @Override
    public Integer batchUpdateAliyunCallRecordCenter(AliyunBatchUpdateCallRecordDTO updateDTO) throws XbbException {
        List<AliyunUpdateCallRecordModelDTO> modelDTOList = updateDTO.getModelDTOList();
        if (CollectionsUtil.isEmpty(modelDTOList)) {
            return 0;
        }
        List<String> callIdList = modelDTOList.stream().map(AliyunUpdateCallRecordModelDTO::getCallId).filter(StringUtil::isNotEmpty).collect(Collectors.toList());
        // 根据通话ID查询通话记录
        Map<String, Object> param = new HashMap<>(3);
        param.put("corpid", updateDTO.getCorpid());
        param.put("callIdIn", callIdList);
        param.put("del", DelEnum.NORMAL.getDel());
        List<CallCenterCallLogEntity> centerCallLogEntityList = callCenterCallLogModel.findEntitys(param);
        if (CollectionUtils.isEmpty(centerCallLogEntityList)) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301088);
        }
        Map<String, Long> callIdMap = new HashMap<>();
        for (CallCenterCallLogEntity callLogEntity : centerCallLogEntityList) {
            if (!callIdMap.containsKey(callLogEntity.getCallId())) {
                callIdMap.put(callLogEntity.getCallId(), callLogEntity.getId());
            }
        }

        List<CallCenterCallLogEntity> list = new ArrayList<>(modelDTOList.size());
        for (AliyunUpdateCallRecordModelDTO modelDTO : modelDTOList) {
            CallCenterCallLogEntity entity = new CallCenterCallLogEntity();
            String callId = modelDTO.getCallId();
            if (StringUtil.isEmpty(callId) || Objects.isNull(callIdMap.get(callId))) {
                continue;
            }
            Long callLogId = callIdMap.get(callId);
            BeanUtils.copyProperties(modelDTO, entity);
            // 删除user
            entity.setUserId(null);
            entity.setAddTime(null);
            entity.setId(callLogId);
            list.add(entity);
        }
        return callCenterCallLogModel.batchUpdateAliyunCallCenter(updateDTO.getCorpid(), list);
    }

    /**
     * 批量新增阿里云呼通话记录
     * 此本新增只是在数据库先插入记录，具体内容待通话结束后保存
     *
     * @param callLogDto 通话记录数据
     * @return 影响行数
     */
    @Override
    public Integer aliyunCallBatchInsert(AliyunCallBatchInsertDTO callLogDto) throws XbbException {
        // 通话记录集合
        List<AliyunCallCenterModelDTO> callLogList = callLogDto.getCallLogList();
        List<String> callIdList = callLogList.stream().map(AliyunCallCenterModelDTO::getCallId).collect(Collectors.toList());
        // 公司ID
        String corpid = callLogDto.getCorpid();
        // 呼叫中心实例ID
        String instanceId = callLogDto.getInstanceId();

        Map<String, Object> param = new HashMap<>(4);
        param.put("del", 0);
        param.put("callIdIn", callIdList);
        param.put("instanceId", instanceId);
        param.put("corpid", corpid);
        List<CallCenterCallLogEntity> entityList = callCenterCallLogModel.findEntitys(param);
        List<String> entityCallIdList = entityList.stream().map(CallCenterCallLogEntity::getCallId).collect(Collectors.toList());
        if (CollectionsUtil.isNotEmpty(entityCallIdList)) {
            callLogList.removeIf(dto -> entityCallIdList.contains(dto.getCallId()));
        }
        List<CallCenterCallLogEntity> callEntityList = new ArrayList<>();
        if (CollectionsUtil.isNotEmpty(callLogList)) {
            for (AliyunCallCenterModelDTO modelDTO : callLogList) {
                callEntityList.add(modelToEntity(modelDTO));
            }
        }
        return callCenterCallLogModel.aliyunCallBatchInsert(callEntityList);
    }

    /**
     * 根据当前人权限获取老的呼叫中心的人员列表，主要为了团队成员需求
     *
     * @param callCallLogListDTO
     * @return
     * @throws XbbException
     */
    @Override
    public List<String> getCallCenterUserListByLoginUser(CallCallLogListDTO callCallLogListDTO) throws XbbException {
        List<String> callCenterUserList = new ArrayList<>();
        CallCenterAccountUserInfoDTO userInfoDTO = new CallCenterAccountUserInfoDTO();
        BeanUtils.copyProperties(callCallLogListDTO, userInfoDTO);
        CallCenterAccountUserInfoVO userInfoVO = callCenterAccountService.getByXbbUserInfo(userInfoDTO);
        if (Objects.isNull(userInfoVO)) {
            callCenterUserList.add("-1");
        } else if (Objects.equals(userInfoVO.getIsAdmin(), 1)) {
            //代表管理员
            return callCenterUserList;
        } else if (Objects.equals(userInfoVO.getIsSupervisor(), 1)) {
            // 部门主管能看到全部门的通话记录（包括未接来电）
            if (callCallLogListDTO.getDepId() != null && callCallLogListDTO.getDepId() > 0L) {
                if (Objects.equals(callCallLogListDTO.getDepId(), userInfoVO.getDepId())) {
                    throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301015);
                }
            } else if (callCallLogListDTO.getDepId() == null && callCallLogListDTO.getAgentUserId() == null) {
                //上面这块的判断不严谨，因为出现数据权限错误的bug，查询发现判断条件除了depId，还有teamId。youli.chen
                callCallLogListDTO.setTeamId(userInfoVO.getTeamId());
                //当前端没有传depId时，这个主管权限有问题
                callCallLogListDTO.setDepId(userInfoVO.getDepId());
                // 输入当前主管的部门id查询部门下的所有员工
                List<Long> depIdIn = new ArrayList<>();
                depIdIn.add(callCallLogListDTO.getDepId());
                List<String> userIdIn = userModel.getUserIdsRecursionDep(depIdIn, callCallLogListDTO.getCorpid(), 1);
                if (CollectionsUtil.isNotEmpty(userIdIn)) {
                    callCenterUserList.addAll(userIdIn);
                }
            }
        } else if (Objects.equals(userInfoVO.getIsAgent(), 1)) {
            callCenterUserList.add(callCallLogListDTO.getUserId());
        } else {
            callCenterUserList.add("-1");
        }
        return callCenterUserList;
    }

    /**
     * description: 根据部门，人员，和时间范围，查询通话记录
     * date: 2022/9/10 10:02 上午
     *
     * @Author jiping.yang
     */
    @Override
    public AliyunCallGetCallListVO getCallList(AliyunCallGetCallListDTO listDTO) throws XbbException{
        AliyunCallGetCallListVO listVO = new AliyunCallGetCallListVO();
        String corpid = listDTO.getCorpid();
        List<Long> deptIdList = listDTO.getDepartId();
        List<String> userIdList = listDTO.getUserList();
        if (CollectionsUtil.isNotEmpty(deptIdList)){
            //获取部门下的所有角色
            List<String> userId = userModel.getDepUserIdList(corpid, listDTO.getDepartId(), 0);
            if (CollectionsUtil.isNotEmpty(userId)){
                userIdList.addAll(userId);
            }
        }
        //获取符合条件的所有录音数据
        if (CollectionsUtil.isEmpty(userIdList)){
            return listVO;
        }
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("del", DelEnum.NORMAL.getDel());
        param.put("userIdIn", userIdList);
        param.put("startCallTime", listDTO.getStartTime());
        param.put("endCallTime", listDTO.getEndTime());
        param.put("durationStart", listDTO.getDuration());
        param.put("columns", "user_id, call_time, duration, record_url, call_id");
        List<CallCenterCallLogEntity> callLogList = callCenterCallLogModel.findEntitys(param);
        //过滤非标准格式的数据
        Integer callTime = 0;
        Iterator<CallCenterCallLogEntity> iterator = callLogList.iterator();
        while (iterator.hasNext()) {
            CallCenterCallLogEntity callLogEntity = iterator.next();
            String url = callLogEntity.getRecordUrl();
            //排除url为空的数据
            if (Objects.isNull(url) || StringUtils.isEmpty(url)){
                iterator.remove();
                continue;
            }
            //排除格式不对的数据
            String suffix = url.substring(url.lastIndexOf(".")+1);
            if (!Objects.equals(suffix, "mp3")){
                iterator.remove();
                continue;
            }
            callTime = callTime + callLogEntity.getDuration();
        }
        listVO.setCallLogList(callLogList);
        listVO.setCallTime(callTime);
        return listVO;
    }

    /**
     * 新增一条优音云呼的通话记录
     *
     * @param dto 云呼的通话记录数据
     * @return 影响行数
     * @throws XbbException 销帮帮异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer addUinYunCallRecord(UinYunCallRecordDTO dto) throws XbbException {
        // 通话ID和呼叫中心实例ID一定不能为空
        if (StringUtils.isBlank(dto.getCallId()) || StringUtils.isBlank(dto.getInstanceId())) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301055);
        }
        CallCenterCallLogEntity entity = uinDtoToEntity(dto);
        Map<String, Object> param = new HashMap<>(4);
        param.put("del", 0);
        param.put("callId", dto.getCallId());
        param.put("instanceId", dto.getInstanceId());
        param.put("callSource", CallCenterCallLogCallSourceEnum.UIN_YUN_CALL.getCode());
        param.put("corpid", dto.getCorpid());
        Integer count = callCenterCallLogModel.getEntitysCount(param);
        if (count > 0) {
            return callCenterCallLogModel.updateYunCall(entity);
        }
        // 添加跟进记录
        List<CallCenterCallLogEntity> list = new ArrayList<>();
        list.add(entity);
        saveCommunicate(list, dto);
        return callCenterCallLogModel.addYunCall(entity);
    }

    /**
     * 云呼分页查询通话记录
     *
     * @param pageDto 分页信息
     * @return 通话记录
     * @throws XbbException 异常
     */
    @Override
    public YunCallRecordPageVO yunCallRecordPage(YunCallPageRecordDTO pageDto) throws XbbException {
        // 获取优音云通话记录查询参数
        BoolQueryBuilder queryBuilder = this.getYunQueryBuilder(pageDto);
        SearchSourceBuilder sourceBuilder = this.getUinYunSource(pageDto, queryBuilder);
        // 分页信息
        PageRequest pageRequest = EsUtil.setPage(sourceBuilder, pageDto.getPageNumber(), pageDto.getPageSize());
        //设置查询路由
        SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG.getIndex());
        searchRequest.source(sourceBuilder);
        // 查询es
        XbbAggregatedPage<CallCenterCallLogEntity> esData = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, CallCenterCallLogEntity.class);
        List<AliyunCallCenterPojo> data = new ArrayList<>();
        if (Objects.nonNull(esData) || CollectionsUtil.isNotEmpty(esData.getContent())) {
            List<CallCenterCallLogEntity> pageList = esData.getContent();
            data = pageList.stream().map(this::entityToPojo).collect(Collectors.toList());
            // 获取号码可见权限信息
            this.getNumberVisibleAuths(data, pageDto);
        }
        PageHelper pageHelper = new PageHelper(pageDto.getPageNumber(), pageDto.getPageSize());
        pageHelper.setRowsCount((int) esData.getTotalElements());
        YunCallRecordPageVO pageVO = new YunCallRecordPageVO();
        pageVO.setData(data);
        pageVO.setPageHelper(pageHelper);
        return pageVO;
    }

    /**
     * 获取当前人员部门下所有的用户ID
     *
     * @param dto 当前人员
     * @return 部门下所有的用户ID
     * @throws XbbException 异常
     */
    @Override
    public List<String> listDepAllUser(YunCallDepAllUserListDTO dto) throws XbbException {
        // 用户ID
        String userId = dto.getUserId();
        // 公司ID
        String corpid = dto.getCorpid();
        UserEntity userEntity = userModel.getByKey(userId, corpid);
        if (userEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100004, SystemErrorCodeEnum.API_ERROR_100004.getMsg());
        }
        Set<Long> departmentIdSet = new HashSet<>();
        formatDepIdSet(userEntity.getDepartment(), departmentIdSet);
        return userModel.getUserIdsRecursionDep(new ArrayList<>(departmentIdSet), corpid);
    }

    /**
     * 优音统计通话记录信息
     *
     * @param dto 请求信息
     * @return 统计通话记录信息
     * @throws XbbException 异常
     */
    @Override
    public UinSumCallRecordVO uinSumCallRecord(UinSumCallRecordDTO dto) throws XbbException {
        UinSumCallRecordVO callRecordVO = new UinSumCallRecordVO();
        getOutboundCount(dto, callRecordVO);
        getInboundCount(dto, callRecordVO);
        return callRecordVO;
    }


    /**
     * 新增一条优音云呼的通话记录
     *
     * @param dto 云呼的通话记录数据
     * @return 影响行数
     * @throws XbbException 销帮帮异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer addExternalCallRecord(ExternalCallRecordDTO dto) throws XbbException {
        // 通话ID和呼叫中心实例ID一定不能为空
        if (StringUtils.isBlank(dto.getCallId()) || StringUtils.isBlank(dto.getInstanceId())) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301055);
        }
        CallCenterCallLogEntity entity = externalDtoToEntity(dto);
        Map<String, Object> param = new HashMap<>(4);
        param.put("del", 0);
        param.put("callId", dto.getCallId());
        param.put("instanceId", dto.getInstanceId());
        param.put("callSource", CallCenterCallLogCallSourceEnum.EXTERNAL_SYSTEM.getCode());
        param.put("corpid", dto.getCorpid());
        Integer count = callCenterCallLogModel.getEntitysCount(param);
        if (count > 0) {
            return callCenterCallLogModel.updateYunCall(entity);
        }
        // 添加跟进记录
        List<CallCenterCallLogEntity> list = new ArrayList<>();
        list.add(entity);
        saveCommunicate(list, dto);
        return callCenterCallLogModel.addYunCall(entity);
    }

    /**
     * 优音统计通话记录信息
     *
     * @param dto 请求信息
     * @return 统计通话记录信息
     * @throws XbbException 异常
     */
    @Override
    public ExternalSumCallRecordVO externalSumCallRecord(ExternalSumCallRecordDTO dto) throws XbbException {
        ExternalSumCallRecordVO callRecordVO = new ExternalSumCallRecordVO();
        getOutboundCount(dto, callRecordVO);
        getInboundCount(dto, callRecordVO);
        return callRecordVO;
    }

    /**
     * 获取号码可见权限信息
     *
//     * @param callCenterPojoList 通话记录
     * @param baseDTO            接口请求类
     * @throws XbbException 异常
     */
    private Boolean getNumberVisibleh(Integer refType,String anotherPhoneNum, BaseDTO baseDTO) throws XbbException {
        // 是否可见
        boolean visible = true;
        String corpid = baseDTO.getCorpid();
//        List<Integer> xbbRefTypeList = Arrays.asList(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), XbbRefTypeEnum.CONTACT.getCode(), XbbRefTypeEnum.CLUE.getCode());
        //  获取员工的数据权限
//        Integer dataPermission = userModel.getDataPermission(userEntity, true);
//        List<String> userIdList = userModel.getSubIdListByDataPermission(dataPermission, baseDTO.getUserId(), baseDTO.getCorpid(), BasicConstant.ZERO,false);
        Map<Long,PaasFormEntityExt> map = new HashMap();
        // 查询表单信息
        int customerManagementCode = XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode();
        int contactCode = XbbRefTypeEnum.CONTACT.getCode();
        int clueCode = XbbRefTypeEnum.CLUE.getCode();
        List businessTypes = new ArrayList();
        businessTypes.add(customerManagementCode);
        businessTypes.add(contactCode);
        businessTypes.add(clueCode);
        List<PaasFormEntityExt> paasFormEntityExts = paasFormModel.getEnableFormList(corpid, businessTypes);
        paasFormEntityExts.forEach(item->{ map.put(item.getId(),item); });
        Map<Long,Boolean> cache = new HashMap();
            PaasFormDataEntityExt paasFormDataEntityExt = null;
            // 根据公司ID和电话查询线索
            CustomerEntityExt cusEntityExt = null;
            // 联系人
            ContactEntityExt contactEntityExt = null;
            // 线索
            ClueEntityExt clueEntityExt = null;
            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(refType);
            switch (xbbRefTypeEnum){
                case CUSTOMER_MANAGEMENT:
                    cusEntityExt = customerModel.getByPhoneIncloudRecycled(corpid, anotherPhoneNum);
                    paasFormDataEntityExt = cusEntityExt;
                    break;
                case CONTACT:
                    // 联系人
                    contactEntityExt = contactModel.getByPhone(corpid, anotherPhoneNum);
                    paasFormDataEntityExt = contactEntityExt;
                    break;
                case CLUE:
                    // 联系人
                    clueEntityExt = clueModel.getByPhoneIncloudRecycled(corpid, anotherPhoneNum);
                    paasFormDataEntityExt = clueEntityExt;
                    break;
                default:
                    return visible;
            }
            Long formId = paasFormDataEntityExt.getFormId();
            // 查询表单信息
            PaasFormEntityExt paasFormEntityExt = map.get(formId);
            if (Objects.isNull(paasFormEntityExt)) {
                return visible;
            }
            // 查询表单解释
            PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(paasFormEntityExt.getId(), corpid);
            if (Objects.isNull(paasFormExplainEntity)) {
                return visible;
            }
            List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            Integer saasMark = paasFormExplainEntity.getSaasMark();
            // 不为空校验
            if (paasFormDataEntityExt == null) {
                return visible;
            }
            // 不为逻辑删除校验
            if (Objects.equals(paasFormDataEntityExt.getDel(),DelEnum.DELETE.getDel())) {
                return visible;
            }
            // 审批校验
            if (FlowStatusEnum.inApproval(paasFormDataEntityExt.getFlowStatus()) ) {
                return visible;
            }
            // 去获取表单模板中的信息
            HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
            BeanUtil.copyProperties(baseDTO, handlerExplainDTO, false);
            handlerExplainDTO.setCreatorId(paasFormDataEntityExt.getCreatorId());
            UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
            BeanUtil.copyProperties(baseDTO, userAndDepartmentGetDTO);
            userAndDepartmentGetDTO.setExplainList(explainList);
            Map<String, UserEntity> userMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            handlerExplainDTO.setExplainList(explainList);
            // 获取协同人和负责人
            paasFormHelp.getOwnerIdAndCoUserId(handlerExplainDTO, saasMark, refType, refType, paasFormDataEntityExt, userMap);
            handlerExplainDTO.setPaasFormEntityExt(paasFormEntityExt);
            handlerExplainDTO.setFormData(paasFormDataEntityExt.getData());
            // 获取表单解释
            HandlerExplainVO handlerExplainVO = formDataDetailFormExplainHandleName.handleExplain(handlerExplainDTO);
            List<FieldAttrEntity> headList = handlerExplainVO.getHeadList();
            // 将表单解释转为MAP key -> 字段名 value -> 为字段解释
            Map<String, FieldAttrEntity> attrEntityMap = headList.stream().collect(Collectors.toMap(FieldAttrEntity::getAttr, fieldAttrEntity -> fieldAttrEntity));
            SubFormPoJo subForm = null;
            switch (xbbRefTypeEnum){
                case CUSTOMER_MANAGEMENT:
                    if(attrEntityMap.containsKey(CustomerManagementEnum.PHONE.getAttr())){
                        // 客户
                        FieldAttrEntity fieldAttrEntity = attrEntityMap.get(CustomerManagementEnum.PHONE.getAttr());
                        subForm = fieldAttrEntity.getSubForm();
                    }
                    break;
                case CONTACT:
                    // 联系人
                    if(attrEntityMap.containsKey(ContactEnum.PHONE.getAttr())){
                        // 联系人
                        FieldAttrEntity fieldAttrEntity = attrEntityMap.get(ContactEnum.PHONE.getAttr());
                        subForm = fieldAttrEntity.getSubForm();
                    }
                    break;
                case CLUE:
                    // 联系人
                    if(attrEntityMap.containsKey(ClueEnum.PHONE.getAttr())){
                        // 销售线索
                        FieldAttrEntity fieldAttrEntity = attrEntityMap.get(ClueEnum.PHONE.getAttr());
                        subForm = fieldAttrEntity.getSubForm();
                    }
                    break;
                default:
                    return visible;
            }

            if (Objects.nonNull(subForm) && CollectionUtils.isNotEmpty(subForm.getItems())){
                FieldAttrEntity attrEntity = subForm.getItems().stream().filter(item -> "text_2".equals(item.getAttr())).findAny().orElse(null);
                visible = Objects.nonNull(attrEntity) && attrEntity.getVisible().equals(1);
            }
        return visible;
    }

    /**
     * 隐藏号码
     *
     * @param phoneNum 号码
     * @return 号码
     */
    private String getHideNumber(String phoneNum){
        if(StringUtils.isBlank(phoneNum)){
            return phoneNum;
        }
        return RegExUtils.replaceAll(phoneNum, "(\\d{3})\\d{4}(\\d{4})","$1****$2");
    }

    public String getSortField(String sortField){
        List<String> keywordList = Arrays.asList("callId", "agentPhoneNum", "anotherPhoneNum", "refName", "userName", "skillGroupNames");
        if(keywordList.contains(sortField)){
            return sortField + ".keyword";
        }
        return sortField;
    }

    @Override
    public AliyunCallcenterListVO aliyunCallCenterWorkbenchList(AliyunCallCenterListDTO aliyunCallCenterListDTO) throws XbbException {
        // 用户ID
        String userId = aliyunCallCenterListDTO.getUserId();
        // 公司ID
        String corpid = aliyunCallCenterListDTO.getCorpid();
        // 校验登录用户
        UserEntity logUser = userModel.getByKey(userId, corpid);
        if (logUser == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.USER_NOT_EXIST);
        }
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        // 查询ES
        return aliyunCallCenterWorkbenchRecordList(boolQueryBuilder, aliyunCallCenterListDTO);
    }

    private AliyunCallcenterListVO aliyunCallCenterWorkbenchRecordList(BoolQueryBuilder boolQueryBuilder, AliyunCallCenterListDTO aliyunCallCenterListDTO) throws XbbException {
        PageHelper pageHelper;
        List<CallCenterCallLogEntity> callLogEntityList;
        try {
            boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, aliyunCallCenterListDTO.getCorpid()));
            RangeQueryBuilder callTimeQuery = null;
            if (Objects.nonNull(aliyunCallCenterListDTO.getStartTime())) {
                callTimeQuery = rangeQuery("callTime");
                callTimeQuery.gte(aliyunCallCenterListDTO.getStartTime());
            }
            if (Objects.nonNull(aliyunCallCenterListDTO.getEndTime())) {
               if(callTimeQuery == null){
                   callTimeQuery = rangeQuery("callTime");
               }
                callTimeQuery.lt(aliyunCallCenterListDTO.getEndTime());
            }
            if(callTimeQuery != null){
                boolQueryBuilder.filter(callTimeQuery);
            }
            Integer type = aliyunCallCenterListDTO.getType();
            if (Objects.nonNull(type)) {
                boolQueryBuilder.filter(rangeQuery("type").gte(type).lte(type));
            }
            Integer result = aliyunCallCenterListDTO.getResult();
            if (Objects.nonNull(result)) {
                boolQueryBuilder.filter(rangeQuery("result").gte(result).lte(result));
            }
            if (StringUtils.isNotBlank(aliyunCallCenterListDTO.getSkillGroupNames())) {
                BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
                innerBoolQueryBuilder.should(matchPhraseQuery("skillGroupNames", aliyunCallCenterListDTO.getSkillGroupNames()));
                innerBoolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
                boolQueryBuilder.filter(innerBoolQueryBuilder);
            }
            if (Objects.nonNull(aliyunCallCenterListDTO.getIsSync())&&aliyunCallCenterListDTO.getIsSync()){
                boolQueryBuilder.filter(termQuery("instanceId.keyword", aliyunCallCenterListDTO.getInstanceId()));
                boolQueryBuilder.mustNot(existsQuery("result"));
            }
            if (StringUtils.isNotBlank(aliyunCallCenterListDTO.getCallId())) {
                boolQueryBuilder.filter(termQuery("callId" + StringConstant.POINT + StringConstant.KEY_WORD, aliyunCallCenterListDTO.getCallId()));
            }
            boolQueryBuilder.filter(termsQuery("callSource", CallCenterCallLogCallSourceEnum.listYunCallCallSource()));
            // 主叫号码
            String agentPhoneNum = aliyunCallCenterListDTO.getAgentPhoneNum();
            // 查询被叫号码
            if (StringUtils.isNotBlank(agentPhoneNum)) {
                BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
                innerBoolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
                innerBoolQueryBuilder.should(matchPhraseQuery("agentPhoneNum", agentPhoneNum));
                boolQueryBuilder.filter(innerBoolQueryBuilder);
            }
            // 主叫号码
            String anotherPhoneNum = aliyunCallCenterListDTO.getAnotherPhoneNum();
            // 查询主叫号码
            if (StringUtils.isNotBlank(anotherPhoneNum)) {
                BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
                innerBoolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
                innerBoolQueryBuilder.should(matchPhraseQuery("anotherPhoneNum", anotherPhoneNum));
                boolQueryBuilder.filter(innerBoolQueryBuilder);
            }
            // 员工
            if (StringUtils.isNotBlank(aliyunCallCenterListDTO.getUserName())) {
                BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
                innerBoolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
                innerBoolQueryBuilder.should(matchPhraseQuery("userName", aliyunCallCenterListDTO.getUserName()));
                boolQueryBuilder.filter(innerBoolQueryBuilder);
            }
            if (CollectionUtils.isNotEmpty(aliyunCallCenterListDTO.getSearchUserIdList())){
                boolQueryBuilder.filter(termsQuery("userId"+ StringConstant.POINT + StringConstant.KEY_WORD, aliyunCallCenterListDTO.getSearchUserIdList().toArray()));
            }
            if (StringUtils.isNotBlank(aliyunCallCenterListDTO.getSearchUserId())) {
                boolQueryBuilder.filter(matchPhraseQuery("userId"+ StringConstant.POINT + StringConstant.KEY_WORD, aliyunCallCenterListDTO.getSearchUserId()));
            }
            if (Objects.nonNull(aliyunCallCenterListDTO.getFuzzySearch())) {
                BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
                innerBoolQueryBuilder.should(matchPhraseQuery("refName", aliyunCallCenterListDTO.getFuzzySearch()));
                innerBoolQueryBuilder.should(matchPhraseQuery("agentPhoneNum", aliyunCallCenterListDTO.getFuzzySearch()));
                innerBoolQueryBuilder.should(matchPhraseQuery("anotherPhoneNum", aliyunCallCenterListDTO.getFuzzySearch()));
                innerBoolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
                boolQueryBuilder.filter(innerBoolQueryBuilder);
            }
            if (Objects.nonNull(aliyunCallCenterListDTO.getFuzzySearch())) {
                BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
                innerBoolQueryBuilder.should(matchPhraseQuery("refName", aliyunCallCenterListDTO.getFuzzySearch()));
                innerBoolQueryBuilder.should(matchPhraseQuery("agentPhoneNum", aliyunCallCenterListDTO.getFuzzySearch()));
                innerBoolQueryBuilder.should(matchPhraseQuery("anotherPhoneNum", aliyunCallCenterListDTO.getFuzzySearch()));
                innerBoolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
                boolQueryBuilder.filter(innerBoolQueryBuilder);
            }
            boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
            IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG;
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            // 搜索条件
            sourceBuilder.query(boolQueryBuilder);
            //分页
            if(StringUtils.isNotBlank(aliyunCallCenterListDTO.getSortField()) && StringUtils.isNotBlank(aliyunCallCenterListDTO.getSort())){
                String sortField = getSortField(aliyunCallCenterListDTO.getSortField());
                SortOrder sort = StringUtils.equalsIgnoreCase(aliyunCallCenterListDTO.getSort(), "desc") ? SortOrder.DESC : SortOrder.ASC;
                sourceBuilder.sort(new FieldSortBuilder(sortField).order(sort));
            } else {
                sourceBuilder.sort(new FieldSortBuilder("addTime").order(SortOrder.DESC));
            }
            PageRequest pageRequest = EsUtil.setPage(sourceBuilder, aliyunCallCenterListDTO.getPage(), aliyunCallCenterListDTO.getPageSize());
            //设置查询路由
            SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
            searchRequest.source(sourceBuilder);
            XbbAggregatedPage<CallCenterCallLogEntity> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, CallCenterCallLogEntity.class);
            if (esEntities == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            callLogEntityList = new ArrayList<>(esEntities.getContent());
            long count = esEntities.getTotalElements();
            pageHelper = new PageHelper(aliyunCallCenterListDTO.getPage(), aliyunCallCenterListDTO.getPageSize());
            pageHelper.setRowsCount((int) count);
        } catch (Exception e) {
            LOG.error("CallCenterCallLogServiceImpl.getCallLogList 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        // 封装已经被转为客户的陌生号码的客户名称
//        this.initCallLogListRefName(aliyunCallCenterListDTO.getCorpid(), callLogEntityList);
        List<AliyunCallCenterPojo> aliyunCallCenterPojos = callLogEntityList.stream().map(this::entityToPojo).collect(Collectors.toList());
//        initCallLogRef(corpid,callLogEntityList);
        AliyunCallcenterListVO callCenterListVO = new AliyunCallcenterListVO();
        // 获取号码可见权限信息
        getNumberVisible(aliyunCallCenterPojos, aliyunCallCenterListDTO);
        callCenterListVO.setAliyunCallCenterPojos(aliyunCallCenterPojos);
        callCenterListVO.setPageHelper(pageHelper);
        callCenterListVO.setTotalElements(pageHelper.getRowsCount());
        callCenterListVO.setTotalPages(pageHelper.getPageTotal());
        return callCenterListVO;
    }
    /**
     * 获取号码可见权限信息
     *
     * @param callCenterPojoList 通话记录
     * @param baseDTO            接口请求类
     * @throws XbbException 异常
     */
    private void getNumberVisible(List<AliyunCallCenterPojo> callCenterPojoList, BaseDTO baseDTO) throws XbbException {
        String corpid = baseDTO.getCorpid();
        if(callCenterPojoList==null||callCenterPojoList.size()==0){
            return;
        }
        List<AliyunCallCenterPojo> inboundLogList = new ArrayList<>();
        List<AliyunCallCenterPojo> outboundLogList = new ArrayList<>();
        callCenterPojoList.forEach(temp->{
            Integer type = temp.getType();
            if(Objects.equals(type,CallLogTypeEnum.INBOUND.getCode())){
                inboundLogList.add(temp);
            }else if(Objects.equals(type,CallLogTypeEnum.OUTBOUND.getCode())){
                outboundLogList.add(temp);
            }
        });
        if(CollectionUtils.isEmpty(outboundLogList)){
            // 因为只有外呼才有是否跟随系统权限
            return;
        }
        CompanyConfigEntity companyConfigEntity = companyConfigModel.getByConfigAlias(CompanyConfigEnum.ALIYUN_CALLCENTER_CONFIGURATION.getAlias(), corpid);
        Integer callDisplay = 0;
        if(Objects.nonNull(companyConfigEntity)){
            String configValueStr = companyConfigEntity.getConfigValue();
            JSONObject configValue = JSON.parseObject(configValueStr);
            // 坐席工作台配置
            Map<String, Integer> configMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            JSONArray seatsWorkbenchJosnArray = configValue.getJSONArray("seatsWorkbench");
            for (int i = 0; i < seatsWorkbenchJosnArray.size(); i++) {
                JSONObject configjson = seatsWorkbenchJosnArray.getJSONObject(i);
                configMap.put(configjson.getString("config"), configjson.getInteger("value"));
            }
            callDisplay = configMap.get("callDisplay");
        }
        //LOG.info("云呼日志：callDisplay "+callDisplay);
        if(Objects.equals(callDisplay,0)){
            // 跟随系统权限
            dealSystemNumberVisible(corpid,outboundLogList,baseDTO);
        }
    }

    private void dealSystemNumberVisible(String corpid,List<AliyunCallCenterPojo> callCenterPojoList, BaseDTO baseDTO) throws XbbException{
        Set<Long> customerIdIn = new HashSet<>();
        Set<Long> clueIdIn = new HashSet<>();
        Set<Long> contactIdIn = new HashSet<>();
        Map<String,List<AliyunCallCenterPojo>> callLogMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        callCenterPojoList.forEach(temp->{
            Integer refBusinessType = temp.getRefType();
            Long refId = temp.getRefId();
            if(Objects.equals(refBusinessType,XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())){
                customerIdIn.add(refId);
            }
            if(Objects.equals(refBusinessType,XbbRefTypeEnum.CLUE.getCode())){
                clueIdIn.add(refId);
            }
            if(Objects.equals(refBusinessType,XbbRefTypeEnum.CONTRACT.getCode())){
                contactIdIn.add(refId);
            }
            String key = refBusinessType+"-"+refId;
            if(callLogMap.containsKey(key)){
                List<AliyunCallCenterPojo> aliyunCallCenterPojos = callLogMap.get(key);
                aliyunCallCenterPojos.add(temp);
            }else{
                List<AliyunCallCenterPojo> aliyunCallCenterPojos = new ArrayList<>();
                aliyunCallCenterPojos.add(temp);
                callLogMap.put(key,aliyunCallCenterPojos);
            }
            temp.setVisible(true);
        });
        List<PaasFormDataEntityExt> customerEntityExtList = customerModel.getByKeys(new ArrayList(customerIdIn), corpid);
        List<PaasFormDataEntityExt> clueEntityExtList = clueModel.getByKeys(new ArrayList(clueIdIn), corpid);
        Map<String,Object> params = new HashMap();
        params.put(StringConstant.CORPID,corpid);
        params.put(StringConstant.IDIN,contactIdIn);
        params.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
        List<? extends PaasFormDataEntityExt> contactEntityExtList = contactModel.findEntitys(params);

        Set<Long> formIdIn = new HashSet<>();
        customerEntityExtList.forEach(temp->{ formIdIn.add(temp.getFormId()); });
        clueEntityExtList.forEach(temp->{ formIdIn.add(temp.getFormId()); });
        contactEntityExtList.forEach(temp->{ formIdIn.add(temp.getFormId()); });
        List<PaasFormExplainEntity> paasFormExplainEntityList = paasFormExplainModel.getByFormIdIn(formIdIn, corpid);

        Map<Long,Map<String, FieldAttrEntity>> paasFormExplainEntityMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        paasFormExplainEntityList.forEach(temp->{
            String explains = temp.getExplains();
            Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explains, null);
            paasFormExplainEntityMap.put(temp.getFormId(),explainMap);
        });

        if(CollectionUtils.isNotEmpty(contactEntityExtList)){
            params.clear();
            params.put(StringConstant.CORPID,corpid);
            params.put("contactIdIn",contactIdIn);
            params.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
            List<UserTeamEntity> contactuserIdList = contactUserModel.findBaseEntitys(params);
            List<UserTeamEntity> mainContactUserIdList =  new ArrayList<>();
            List<UserTeamEntity> coContactUserIdList =  new ArrayList<>();
            contactuserIdList.forEach(temp->{
                Integer isMain = temp.getIsMain();
                if(Objects.equals(isMain,1)){
                    mainContactUserIdList.add(temp);
                }else{
                    coContactUserIdList.add(temp);
                }
            });
            setVisible(clueEntityExtList,mainContactUserIdList,coContactUserIdList
                    , baseDTO,paasFormExplainEntityMap,
                    callLogMap,ContactEnum.PHONE.getAttr(),XbbRefTypeEnum.CONTACT.getCode());
        }
        if(CollectionUtils.isNotEmpty(clueEntityExtList)){
            params.clear();
            params.put(StringConstant.CORPID,corpid);
            params.put("dataIdIn",clueIdIn);
            params.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
            List<UserTeamEntity> clueuserIdList = clueUserModel.findEntitys(params);
            List<UserTeamEntity> mainClueUserIdList =  new ArrayList<>();
            List<UserTeamEntity> coClueUserIdList =  new ArrayList<>();
            clueuserIdList.forEach(temp->{
                Integer isMain = temp.getIsMain();
                if(Objects.equals(isMain,1)){
                    mainClueUserIdList.add(temp);
                }else{
                    coClueUserIdList.add(temp);
                }
            });

            setVisible(clueEntityExtList,mainClueUserIdList,coClueUserIdList
                    , baseDTO,paasFormExplainEntityMap,
                    callLogMap,ClueEnum.PHONE.getAttr(),XbbRefTypeEnum.CLUE.getCode());
        }

        if(CollectionUtils.isNotEmpty(customerEntityExtList)){
            params.clear();
            params.put(StringConstant.CORPID,corpid);
            params.put("customerIdIn",customerIdIn);
            params.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
            List<UserTeamEntity> userIdList = customerUserModel.findBaseEntitys(params);
            List<UserTeamEntity> mainCustomerUserIdList = new ArrayList<>();
            List<UserTeamEntity> coCustomerUserIdList =  new ArrayList<>();
            userIdList.forEach(temp->{
                Integer isMain = temp.getIsMain();
                if(Objects.equals(isMain,1)){
                    mainCustomerUserIdList.add(temp);
                }else{
                    coCustomerUserIdList.add(temp);
                }
            });
            setVisible(customerEntityExtList,mainCustomerUserIdList,coCustomerUserIdList
                    , baseDTO,paasFormExplainEntityMap,
                    callLogMap,CustomerManagementEnum.PHONE.getAttr(),XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
        }


    }

    private void setVisible(List<? extends PaasFormDataEntityExt> customerEntityExtList,
                            List<UserTeamEntity> mainCustomerUserIdList,List<UserTeamEntity> coCustomerUserIdList
                            ,BaseDTO baseDTO,Map<Long,Map<String, FieldAttrEntity>> paasFormExplainEntityMap,
                            Map<String,List<AliyunCallCenterPojo>> callLogMap,String phoneAttr,Integer businessType )throws XbbException{
        if(CollectionUtils.isNotEmpty(customerEntityExtList)){
            Map<Long, List<String>> mainCustomerUserIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<Long, List<String>> coCustomerUserIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            mainCustomerUserIdMap = mainCustomerUserIdList.stream().
                    collect(Collectors.toMap(UserTeamEntity::getDataId,
                            userEntity -> new ArrayList<>(Arrays.asList(userEntity.getUserId())),
                            (List<String> oldList, List<String> newList) -> {
                                oldList.addAll(newList);
                                return oldList;
                            }));
            coCustomerUserIdMap = coCustomerUserIdList.stream().
                    collect(Collectors.toMap(UserTeamEntity::getDataId,
                            userEntity -> new ArrayList<>(Arrays.asList(userEntity.getUserId())),
                            (List<String> oldList, List<String> newList) -> {
                                oldList.addAll(newList);
                                return oldList;
                            }));

            Map<Long, List<String>> finalMainCustomerUserIdMap = mainCustomerUserIdMap;
            Map<Long, List<String>> finalCoCustomerUserIdMap = coCustomerUserIdMap;
            customerEntityExtList.forEach(temp-> {
                try {
                    Long id = temp.getId();
                    String creatorId = temp.getCreatorId();
                    Long formId = temp.getFormId();
                    // 当前数据的创建人、负责人、协同人、当前操作人
                    HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
                    BeanUtil.copyProperties(baseDTO, handlerExplainDTO);
                    handlerExplainDTO.setOwnerId(finalMainCustomerUserIdMap.getOrDefault(id, new ArrayList<>()));
                    handlerExplainDTO.setCoUserId(finalCoCustomerUserIdMap.getOrDefault(id, new ArrayList<>()));
                    handlerExplainDTO.setCreatorId(creatorId);
                    Map<String, FieldAttrEntity> explainMap = paasFormExplainEntityMap.get(formId);
                    if(explainMap == null){
                        return;
                    }
                    // 客户
                    FieldAttrEntity fieldAttrEntity = explainMap.get(phoneAttr);
                    SubFormPoJo subForm = fieldAttrEntity.getSubForm();
                    Boolean fieldNeedHide = ExplainUtil.isFieldNeedHide(fieldAttrEntity, handlerExplainDTO);
                    // 是否可见
                    Boolean subFieldNeedHide = null;
                    // 里面的字段
                    if (Objects.nonNull(subForm) && CollectionUtils.isNotEmpty(subForm.getItems())) {
                        FieldAttrEntity attrEntity = subForm.getItems().stream().filter(item -> "text_2".equals(item.getAttr())).findAny().orElse(null);
                        subFieldNeedHide = ExplainUtil.isFieldNeedHide(attrEntity, handlerExplainDTO);
                    }
                    String key = businessType + "-" + id;
                    boolean visible = !fieldNeedHide && !subFieldNeedHide;
                    //LOG.info("云呼日志：id {},businessType:{},visible {},fieldNeedHide {}, subFieldNeedHide {}",id,businessType,visible,fieldNeedHide,subFieldNeedHide);
                    List<AliyunCallCenterPojo> aliyunCallCenterPojos = callLogMap.get(key);
                    if (CollectionUtils.isNotEmpty(aliyunCallCenterPojos)) {
                        aliyunCallCenterPojos.forEach(item -> {
                            item.setVisible(visible);
                        });
                    }
                } catch (XbbException e) {
                    LOG.error("com.xbongbong.paas.service.impl.CallCenterCallLogServiceImpl.setVisible", e);
                }
            });
        }
    }

    /**
     * 获取号码可见权限信息
     *
     * @param callCenterPojoList 通话记录
     * @param baseDTO            接口请求类
     * @throws XbbException 异常
     */
    private void getNumberVisibleAuths(List<AliyunCallCenterPojo> callCenterPojoList, YunCallRecordDTO baseDTO) throws XbbException {
        if (CollectionsUtil.isEmpty(callCenterPojoList)) {
            return ;
        }
        // 公司ID
        String corpid = baseDTO.getCorpid();
        // 当前登陆人有权限的客户表单模版
        UserVO loginUserVO = baseDTO.getLoginUser();
        if (Objects.isNull(loginUserVO)) {
            loginUserVO = new UserVO();
            UserEntity logUser = userModel.getByKey(baseDTO.getUserId(), baseDTO.getCorpid());
            if (Objects.isNull(logUser)){
                throw new XbbException(ClueErrorCodeEnum.API_ERROR_1110013);
            }
            BeanUtils.copyProperties(logUser, loginUserVO);
        }
        UserEntity userEntity = new UserEntity();
        BeanUtils.copyProperties(loginUserVO, userEntity);
        //  获取员工的数据权限
        Integer dataPermission = userModel.getDataPermission(userEntity, true);
        List<String> userIdList = userModel.getSubIdListByDataPermission(dataPermission, baseDTO.getUserId(), baseDTO.getCorpid(), BasicConstant.ONE,false);
        // 当前登陆人有权限的客户表单模版
        List<PaasFormEntityExt> paasFormEntityExtList = paasFormService.getEnableCustomerFormList(loginUserVO);
        Set<String> anotherPhoneNumSet = new HashSet<>();
        Set<String> userIdSet = new HashSet<>();
        for (AliyunCallCenterPojo pojo : callCenterPojoList) {
            anotherPhoneNumSet.add(Objects.nonNull(pojo.getType()) && pojo.getType().equals(0) ? pojo.getAgentPhoneNum() : pojo.getAnotherPhoneNum());
            if (StringUtil.isNotEmpty(pojo.getUserId())) {
                String[] split = pojo.getUserId().split(",");
                userIdSet.addAll(Arrays.asList(split));
            }
        }
        // 获取用户信息
        List<UserEntity> userEntityList = userModel.getByUserIdIn(corpid, userIdSet, false);
        Map<String, String> userEntityMap = new HashMap<>(16);
        if (CollectionsUtil.isNotEmpty(userEntityList)) {
            userEntityMap = userEntityList.stream()
                    .filter(entity -> !Objects.equals(entity.getDel(),  DelEnum.NORMAL.getDel()))
                    .collect(Collectors.toMap(UserEntity::getUserId, entity ->  entity.getName() + StringConstant.LEAVE_ANOTHER_MARK));
        }
        // 根据号码获取客户信息集合
        Map<String, PaasFormDataEntityExt> customerEntityExtMap = this.listCustomerOrContactOrClueEntityExtMap(corpid, anotherPhoneNumSet);
        Map<Long, PaasFormExplainEntity> paasFormEntityExtMap = new HashMap<>();
        Map<Long, PaasFormEntityExt> paasFormEntityMap = new HashMap<>();
        // 只有配置了跟新系统权限才需要去查询
        Boolean isSysVisible = Objects.nonNull(baseDTO.getIsSysVisible()) && baseDTO.getIsSysVisible();
        if (isSysVisible) {
            // 获取所有号码的表单解释
            paasFormEntityExtMap = this.listPaasFormExplainEntityMap(customerEntityExtMap, corpid);
            // 获取所有号码的表单
            paasFormEntityMap = this.listPaasFormEntityMap(paasFormEntityExtMap.keySet(), corpid);
        }
        // 获取用户
        List<CallCenterCallLogEntity> updateEntityList = new ArrayList<>();
        for (AliyunCallCenterPojo callCenterPojo : callCenterPojoList) {
            this.initAliyunCallLogListRefName(callCenterPojo, customerEntityExtMap, updateEntityList, userEntityMap);
            // 默认都是不可穿透
            callCenterPojo.setIsPenetrate(0);
            callCenterPojo.setVisible(true);
            Integer businessType = callCenterPojo.getRefType();
            if(Objects.equals(XbbRefTypeEnum.UNKNOWN.getCode(), businessType)){
                if (paasFormEntityExtList.isEmpty()) {
                    continue;
                }
                this.setDefaultPenetrateInfo(paasFormEntityExtList.get(0), callCenterPojo);
                continue;
            }
            String phoneNum = Objects.nonNull(callCenterPojo.getType()) && callCenterPojo.getType().equals(0) ? callCenterPojo.getAgentPhoneNum() : callCenterPojo.getAnotherPhoneNum() ;
            if (!customerEntityExtMap.containsKey(phoneNum)){
                continue;
            }
            PaasFormDataEntityExt paasFormDataEntityExt = customerEntityExtMap.get(phoneNum);
            Long formId = paasFormDataEntityExt.getFormId();
            // 权限判断
            if (userIdList.contains(paasFormDataEntityExt.getOwnerId())){
                CallLogExplainPojo entity = new CallLogExplainPojo();
                BeanUtil.copyProperties(paasFormDataEntityExt, entity);
                entity.setBusinessType(paasFormDataEntityExt.getBusinessType());
                entity.setSaasMark(SaasMarkEnum.SAAS.getCode());
                if (Objects.equals(paasFormDataEntityExt.getBusinessType(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())
                        && Objects.equals(DelEnum.DELETE.getDel(), paasFormDataEntityExt.getDel())) {
                    entity.setSubBusinessType(XbbRefTypeEnum.CUSTOMER_RECYCLE.getCode());
                }
                callCenterPojo.setEntity(entity);
                callCenterPojo.setIsPenetrate(1);
            }
            if (!isSysVisible) {
                continue;
            }
            // 呼入不需要去查询解释是否需要隐藏号码
            if (Objects.nonNull(callCenterPojo.getType()) && Objects.equals(callCenterPojo.getType(), 0)) {
                continue;
            }
            if (!paasFormEntityExtMap.containsKey(formId) || !paasFormEntityMap.containsKey(formId)){
                continue;
            }
            PaasFormExplainEntity paasFormExplainEntity = paasFormEntityExtMap.get(formId);
            List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            // 去获取表单模板中的信息
            HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
            BeanUtil.copyProperties(baseDTO, handlerExplainDTO, false);
            handlerExplainDTO.setCreatorId(paasFormDataEntityExt.getCreatorId());
            UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
            BeanUtil.copyProperties(baseDTO, userAndDepartmentGetDTO);
            userAndDepartmentGetDTO.setExplainList(explainList);
            Map<String, UserEntity> userMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            handlerExplainDTO.setExplainList(explainList);
            // 获取协同人和负责人
            paasFormHelp.getOwnerIdAndCoUserId(handlerExplainDTO, paasFormExplainEntity.getSaasMark(), businessType, businessType, paasFormDataEntityExt, userMap);
            handlerExplainDTO.setPaasFormEntityExt(paasFormEntityMap.get(formId));
            handlerExplainDTO.setFormData(paasFormDataEntityExt.getData());
            // 获取表单解释
            HandlerExplainVO handlerExplainVO = formDataDetailFormExplainHandleName.handleExplain(handlerExplainDTO);
            List<FieldAttrEntity> headList = handlerExplainVO.getHeadList();
            // 将表单解释转为MAP key -> 字段名 value -> 为字段解释
            Map<String, FieldAttrEntity> attrEntityMap = headList.stream().collect(Collectors.toMap(FieldAttrEntity::getAttr, fieldAttrEntity -> fieldAttrEntity));
            SubFormPoJo subForm = null;
            // 客户
            if(businessType == XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode() && attrEntityMap.containsKey(CustomerManagementEnum.PHONE.getAttr())){
                FieldAttrEntity fieldAttrEntity = attrEntityMap.get(CustomerManagementEnum.PHONE.getAttr());
                subForm = fieldAttrEntity.getSubForm();
                // 联系人
            } else if (businessType == XbbRefTypeEnum.CONTACT.getCode() && attrEntityMap.containsKey(ContactEnum.PHONE.getAttr())){
                FieldAttrEntity fieldAttrEntity = attrEntityMap.get(ContactEnum.PHONE.getAttr());
                subForm = fieldAttrEntity.getSubForm();
                // 销售线索
            } else if (businessType == XbbRefTypeEnum.CLUE.getCode() && attrEntityMap.containsKey(ClueEnum.PHONE.getAttr())){
                FieldAttrEntity fieldAttrEntity = attrEntityMap.get(ClueEnum.PHONE.getAttr());
                subForm = fieldAttrEntity.getSubForm();
            }
            // 是否可见
            boolean visible = true;
            if (Objects.nonNull(subForm) && CollectionUtils.isNotEmpty(subForm.getItems())){
                FieldAttrEntity attrEntity = subForm.getItems().stream().filter(item -> StringConstant.PHONE_TEL_ATTR.equals(item.getAttr())).findAny().orElse(null);
                visible = Objects.nonNull(attrEntity) && attrEntity.getVisible().equals(1);
            }
            callCenterPojo.setVisible(visible);
        }
        if (CollectionsUtil.isNotEmpty(updateEntityList)) {
            callCenterCallLogModel.batchUpdateAliyunCallCenter(corpid, updateEntityList);
        }
    }


    private void setDefaultPenetrateInfo(PaasFormEntityExt entityExt, AliyunCallCenterPojo callCenterPojo){
        CallLogExplainPojo customerEntityExplain = new CallLogExplainPojo();
        // 客户的第一个表单模版
        customerEntityExplain.setMenuId(entityExt.getMenuId());
        customerEntityExplain.setFormId(entityExt.getId());
        customerEntityExplain.setAppId(entityExt.getAppId());
        customerEntityExplain.setSaasMark(SaasMarkEnum.SAAS.getCode());
        customerEntityExplain.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
        customerEntityExplain.setSubBusinessType(XbbRefTypeEnum.CUSTOMER.getCode());
        callCenterPojo.setEntity(customerEntityExplain);
        callCenterPojo.setIsPenetrate(1);
    }

    /**
     * 根据号码获取客户、联系人、线索信息集合
     *
     * @param corpid       公司ID
     * @param phoneNumLsit 号码集合
     * @return 客户信息集合
     * @throws XbbException 异常
     */
    private Map<String, PaasFormDataEntityExt> listCustomerOrContactOrClueEntityExtMap(String corpid, Collection<String> phoneNumLsit) throws XbbException {
        // 根据号码集合查询客户
        List<CustomerEntityExt> customerEntityExtList = customerModel.listByInPhone(corpid, new ArrayList<>(phoneNumLsit), true);
        Map<String, PaasFormDataEntityExt> paasFormDataEntityExtMap = new HashMap<>(16);
        if (CollectionUtils.isNotEmpty(customerEntityExtList)) {
            for (CustomerEntityExt entityExt : customerEntityExtList) {
                List<String> phoneNumberList = this.getPhoneNumber(entityExt.getData(), CustomerManagementEnum.PHONE.getAttr());
                if (CollectionsUtil.isNotEmpty(phoneNumberList)) {
                    for (String phoneNumber : phoneNumberList) {
                        if (!paasFormDataEntityExtMap.containsKey(phoneNumber)) {
                            entityExt.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                            paasFormDataEntityExtMap.put(phoneNumber, entityExt);
                        }
                    }
                }
            }
        }
        // 按手机号查询联系人
        List<ContactEntityExt> contactEntityExtList = contactModel.listByInPhone(corpid, new ArrayList<>(phoneNumLsit));
        if (CollectionUtils.isNotEmpty(contactEntityExtList)) {
            for (ContactEntityExt entityExt : contactEntityExtList) {
                List<String> phoneNumberList = this.getPhoneNumber(entityExt.getData(), ContactEnum.PHONE.getAttr());
                if (CollectionsUtil.isNotEmpty(phoneNumberList)) {
                    for (String phoneNumber : phoneNumberList) {
                        if (!paasFormDataEntityExtMap.containsKey(phoneNumber)) {
                            entityExt.setBusinessType(XbbRefTypeEnum.CONTACT.getCode());
                            paasFormDataEntityExtMap.put(phoneNumber, entityExt);
                        }
                    }
                }
            }
        }
        // 按手机号查询线索
        List<ClueEntityExt> clueEntityExtList = clueModel.listByInPhone(corpid, new ArrayList<>(phoneNumLsit),true);
        if (CollectionUtils.isNotEmpty(clueEntityExtList)) {
            for (ClueEntityExt entityExt : clueEntityExtList) {
                List<String> phoneNumberList = this.getPhoneNumber(entityExt.getData(), ClueEnum.PHONE.getAttr());
                if (CollectionsUtil.isNotEmpty(phoneNumberList)) {
                    for (String phoneNumber : phoneNumberList) {
                        if (!paasFormDataEntityExtMap.containsKey(phoneNumber)) {
                            entityExt.setBusinessType(XbbRefTypeEnum.CLUE.getCode());
                            paasFormDataEntityExtMap.put(phoneNumber, entityExt);
                        }
                    }
                }
            }
        }
        return paasFormDataEntityExtMap;
    }

    private Map<Long, PaasFormExplainEntity> listPaasFormExplainEntityMap(Map<String, PaasFormDataEntityExt> paasFormDataEntityExtMap, String corpid) throws XbbException {
        Set<Long> fromIdList = new HashSet<>();
        if (MapUtils.isNotEmpty(paasFormDataEntityExtMap)) {
            paasFormDataEntityExtMap.forEach((key ,value) -> {
                if (Objects.nonNull(value) && Objects.nonNull(value.getFormId())) {
                    fromIdList.add(value.getFormId());
                }
            });
        }
        if (CollectionsUtil.isEmpty(fromIdList)) {
            return new HashMap<>();
        }
        // 查询表单解释
        List<PaasFormExplainEntity> paasFormExplainEntity = paasFormExplainModel.getByFormIdIn(fromIdList, corpid);
        if (CollectionsUtil.isEmpty(paasFormExplainEntity)) {
            return new HashMap<>();
        }
        return paasFormExplainEntity.stream().collect(Collectors.toMap(PaasFormExplainEntity::getFormId, entity -> entity));
    }

    private Map<Long, PaasFormEntityExt> listPaasFormEntityMap(Collection<Long> fromIdList, String corpid) {
        if (CollectionsUtil.isEmpty(fromIdList)) {
            return new HashMap<>();
        }
        Map<String, Object> param = new HashMap<>();
        param.put("corpid", corpid);
        param.put("idIn", new ArrayList<>(fromIdList));
        param.put("del", 0);
        List<PaasFormEntityExt> paasFormEntity = paasFormModel.findEntitys(param);
        return paasFormEntity.stream().collect(Collectors.toMap(PaasFormEntity::getId, entity -> entity));
    }

    private List<String> getPhoneNumber(JSONObject data, String attr){
        if (MapUtils.isEmpty(data) || StringUtil.isEmpty(attr) || CollectionsUtil.isEmpty(data.getJSONArray(attr))) {
            return new ArrayList<>();
        }
        JSONArray jsonArray = data.getJSONArray(attr);
        List<String> phoneNumberList = new ArrayList<>(jsonArray.size());
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            if (jsonObject.containsKey(StringConstant.PHONE_TEL_ATTR)) {
                phoneNumberList.add(jsonObject.getString(StringConstant.PHONE_TEL_ATTR));
            }
        }
        return phoneNumberList;
    }

    /**
     * 获取云呼通话记录的es查询条件
     *
     * @param aliyunCallCenterListDTO 请求信息
     * @return es查询条件
     */
    private BoolQueryBuilder getAliyunCallCenterRecordEsQueryParam(AliyunCallCenterListDTO aliyunCallCenterListDTO){
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, aliyunCallCenterListDTO.getCorpid()));
        if (CollectionsUtil.isEmpty(aliyunCallCenterListDTO.getCallSourceList())) {
            boolQueryBuilder.filter(termsQuery("callSource", CallCenterCallLogCallSourceEnum.listYunCallCallSource()));
        } else {
            boolQueryBuilder.filter(termsQuery("callSource", aliyunCallCenterListDTO.getCallSourceList()));
        }

        RangeQueryBuilder callTimeQuery = null;
        if (Objects.nonNull(aliyunCallCenterListDTO.getStartTime())) {
            callTimeQuery = rangeQuery("callTime");
            callTimeQuery.gte(aliyunCallCenterListDTO.getStartTime());
        }
        if (Objects.nonNull(aliyunCallCenterListDTO.getEndTime())) {
            if(callTimeQuery == null){
                callTimeQuery = rangeQuery("callTime");
            }
            callTimeQuery.lt(aliyunCallCenterListDTO.getEndTime());
        }
        if(callTimeQuery != null){
            boolQueryBuilder.filter(callTimeQuery);
        }
        Integer type = aliyunCallCenterListDTO.getType();
        if (Objects.nonNull(type)) {
            boolQueryBuilder.filter(rangeQuery("type").gte(type).lte(type));
        }
        Integer result = aliyunCallCenterListDTO.getResult();
        if (Objects.nonNull(result)) {
            boolQueryBuilder.filter(rangeQuery("result").gte(result).lte(result));
        }
        if (StringUtils.isNotBlank(aliyunCallCenterListDTO.getSkillGroupNames())) {
            BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
            innerBoolQueryBuilder.should(matchPhraseQuery("skillGroupNames", aliyunCallCenterListDTO.getSkillGroupNames()));
            innerBoolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
            boolQueryBuilder.filter(innerBoolQueryBuilder);
        }
        if (Objects.nonNull(aliyunCallCenterListDTO.getIsSync())&&aliyunCallCenterListDTO.getIsSync()){
            boolQueryBuilder.filter(termQuery("instanceId.keyword", aliyunCallCenterListDTO.getInstanceId()));
            boolQueryBuilder.mustNot(existsQuery("result"));
        }
        if (StringUtils.isNotBlank(aliyunCallCenterListDTO.getCallId())) {
            boolQueryBuilder.filter(termQuery("callId" + StringConstant.POINT + StringConstant.KEY_WORD, aliyunCallCenterListDTO.getCallId()));
        }
        // 主叫号码
        String agentPhoneNum = aliyunCallCenterListDTO.getAgentPhoneNum();
        // 查询被叫号码
        if (StringUtils.isNotBlank(agentPhoneNum)) {
            BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
            innerBoolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
            innerBoolQueryBuilder.should(matchPhraseQuery("agentPhoneNum", agentPhoneNum));
            boolQueryBuilder.filter(innerBoolQueryBuilder);
        }
        // 主叫号码
        String anotherPhoneNum = aliyunCallCenterListDTO.getAnotherPhoneNum();
        // 查询主叫号码
        if (StringUtils.isNotBlank(anotherPhoneNum)) {
            BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
            innerBoolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
            innerBoolQueryBuilder.should(matchPhraseQuery("anotherPhoneNum", anotherPhoneNum));
            boolQueryBuilder.filter(innerBoolQueryBuilder);
        }
        // 员工
        if (StringUtils.isNotBlank(aliyunCallCenterListDTO.getUserName())) {
            BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
            innerBoolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
            innerBoolQueryBuilder.should(matchPhraseQuery("userName", aliyunCallCenterListDTO.getUserName()));
            boolQueryBuilder.filter(innerBoolQueryBuilder);
        }
        if (CollectionUtils.isNotEmpty(aliyunCallCenterListDTO.getSearchUserIdList())){
            boolQueryBuilder.filter(termsQuery("userId"+ StringConstant.POINT + StringConstant.KEY_WORD, aliyunCallCenterListDTO.getSearchUserIdList().toArray()));
        } else if (StringUtils.isNotBlank(aliyunCallCenterListDTO.getSearchUserId())) {
            boolQueryBuilder.filter(termQuery("userId"+ StringConstant.POINT + StringConstant.KEY_WORD, aliyunCallCenterListDTO.getSearchUserId()));
        }
        if (Objects.nonNull(aliyunCallCenterListDTO.getFuzzySearch())) {
            BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
            innerBoolQueryBuilder.should(matchPhraseQuery("refName", aliyunCallCenterListDTO.getFuzzySearch()));
            innerBoolQueryBuilder.should(matchPhraseQuery("agentPhoneNum", aliyunCallCenterListDTO.getFuzzySearch()));
            innerBoolQueryBuilder.should(matchPhraseQuery("anotherPhoneNum", aliyunCallCenterListDTO.getFuzzySearch()));
            innerBoolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
            boolQueryBuilder.filter(innerBoolQueryBuilder);
        }
        boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG;
        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
        return boolQueryBuilder;
    }

    /**
     * 封装已经被转为客户的陌生号码的客户名称
     *
     * @param callCenterPojo   通话记录
     * @param dataEntityExtMap 电话关联的信息
     * @param updateEntityList 需要跟新的集合
     * @throws XbbException 异常
     */
    private void initAliyunCallLogListRefName(AliyunCallCenterPojo callCenterPojo, Map<String, PaasFormDataEntityExt> dataEntityExtMap,
                                              List<CallCenterCallLogEntity> updateEntityList,  Map<String, String> userEntityMap) throws XbbException {
        CallCenterCallLogEntity entity = new CallCenterCallLogEntity();
        entity.setId(callCenterPojo.getId());
        entity.setCorpid(callCenterPojo.getCorpid());
        String phoneNum = Objects.nonNull(callCenterPojo.getType()) && callCenterPojo.getType().equals(0) ? callCenterPojo.getAgentPhoneNum() : callCenterPojo.getAnotherPhoneNum() ;
        if (StringUtil.isNotEmpty(callCenterPojo.getUserId())) {
            String[] userIds = callCenterPojo.getUserId().split(",");
            StringJoiner userName = new StringJoiner(",");
            for (String userId : userIds) {
                if (userEntityMap.containsKey(userId)) {
                    userName.add(userEntityMap.get(userId));
                }
            }
            if (StringUtil.isNotEmpty(userName.toString())) {
                callCenterPojo.setUserName(userName.toString());
                entity.setUserName(userName.toString());
            }
        }
        if (dataEntityExtMap.containsKey(phoneNum) && MapUtils.isNotEmpty(dataEntityExtMap.get(phoneNum).getData())) {
            PaasFormDataEntityExt dataEntityExt = dataEntityExtMap.get(phoneNum);
            if (Objects.equals(XbbRefTypeEnum.UNKNOWN.getCode(), callCenterPojo.getRefType())) {
                entity.setRefId(dataEntityExt.getId());
                entity.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(dataEntityExt.getData(), ManagementBaseEnum.NAME.getAttr(), ""));
                entity.setRefType(dataEntityExt.getBusinessType());
                callCenterPojo.setRefId(dataEntityExt.getId());
                callCenterPojo.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(dataEntityExt.getData(), ManagementBaseEnum.NAME.getAttr(), ""));
                callCenterPojo.setRefType(dataEntityExt.getBusinessType());
                updateEntityList.add(entity);
            } else if(!Objects.equals(dataEntityExt.getId(), callCenterPojo.getRefId())) {
                entity.setRefId(dataEntityExt.getId());
                entity.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(dataEntityExt.getData(), CustomerManagementEnum.NAME.getAttr(), ""));
                entity.setRefType(dataEntityExt.getBusinessType());
                callCenterPojo.setRefId(dataEntityExt.getId());
                callCenterPojo.setRefName(FastJsonHelper.getStringOrDefaultFromFormData(dataEntityExt.getData(), CustomerManagementEnum.NAME.getAttr(), ""));
                callCenterPojo.setRefType(dataEntityExt.getBusinessType());
                updateEntityList.add(entity);
            }
        } else if (!dataEntityExtMap.containsKey(phoneNum) && !Objects.equals(XbbRefTypeEnum.UNKNOWN.getCode(), callCenterPojo.getRefType())) {
            entity.setRefId(0L);
            entity.setRefName("--");
            entity.setRefType(CallCenterTypeEnum.UNKNOWN.getCode());
            callCenterPojo.setRefId(0L);
            callCenterPojo.setRefName("--");
            callCenterPojo.setRefType(CallCenterTypeEnum.UNKNOWN.getCode());
            updateEntityList.add(entity);
        }
    }


    /**
     * description:    摘要设置默认值
     * date: 2021/10/18 9:08 上午
     * @Author yingjf
     */
    public void setSummaryDefaultValue( List<SummaryDataPoJo> summaryList){
        if(CollectionUtils.isEmpty(summaryList)){
            return;
        }
        for(SummaryDataPoJo temp: summaryList){
            List<Object> value = temp.getValue();
            if(CollectionUtils.isEmpty(value)||value.size()==0){
                value = new ArrayList<>();
                value.add("-");
                temp.setValue(value);
            }
        }
    }

    private CallCenterCallLogEntity externalDtoToEntity(ExternalCallRecordDTO dto) throws XbbException {
        // 公司ID
        String corpid = dto.getCorpid();
        CallCenterCallLogEntity callLogEntity = new CallCenterCallLogEntity();
        BeanUtils.copyProperties(dto, callLogEntity);
        UserEntity userEntity = userModel.getByKey(callLogEntity.getUserId(), corpid);
        callLogEntity.setUserName(userEntity.getName());
        callLogEntity.setCallTime(Objects.nonNull(dto.getCallTime()) ? dto.getCallTime().intValue() : null);
        callLogEntity.setRingTime(Objects.nonNull(dto.getRingTime()) ? dto.getRingTime().intValue() : null);
        callLogEntity.setAddTime(Objects.nonNull(dto.getAddTime()) ? dto.getAddTime().intValue() : DateUtil.getInt());
        // 客户号码
        String aliyunSteasPhoneNum = Objects.nonNull(dto.getType()) && dto.getType().equals(0) ? dto.getAgentPhoneNum() : dto.getAnotherPhoneNum();
        if (StringUtil.isNotEmpty(aliyunSteasPhoneNum)) {
            // 根据公司ID和电话查询线索
            CustomerEntityExt cusEntityExt = customerModel.getByPhoneIncloudRecycled(corpid, aliyunSteasPhoneNum);
            ContactEntityExt contactEntityExt = null;
            if (Objects.nonNull(cusEntityExt)) {
                callLogEntity.setRefId(cusEntityExt.getId());
                String name = FastJsonHelper.getStringOrDefaultFromFormData(cusEntityExt.getData(), CustomerManagementEnum.NAME.getAttr(), "");
                callLogEntity.setRefName(name);
                callLogEntity.setRefType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
            } else {
                // 联系人
                contactEntityExt = contactModel.getByPhone(corpid, aliyunSteasPhoneNum);
                if (Objects.nonNull(contactEntityExt)) {
                    Long contactId = contactEntityExt.getId();
                    callLogEntity.setRefId(contactId);
                    String name = FastJsonHelper.getStringOrDefaultFromFormData(contactEntityExt.getData(), ContactEnum.NAME.getAttr(), "");
                    callLogEntity.setRefName(name);
                    callLogEntity.setRefType(XbbRefTypeEnum.CONTACT.getCode());
                }
            }
            if (Objects.isNull(cusEntityExt) && Objects.isNull(contactEntityExt)) {
                // 线索
                ClueEntityExt clueEntityExt = clueModel.getByPhoneIncloudRecycled(corpid, aliyunSteasPhoneNum);
                if (Objects.nonNull(clueEntityExt)) {
                    Long clueId = clueEntityExt.getId();
                    callLogEntity.setRefId(clueId);
                    String name = FastJsonHelper.getStringOrDefaultFromFormData(clueEntityExt.getData(), ClueEnum.COMPANY_NAME.getAttr(), "");
                    callLogEntity.setRefName(name);
                    callLogEntity.setRefType(XbbRefTypeEnum.CLUE.getCode());
                } else {
                    callLogEntity.setRefId(0L);
                    callLogEntity.setRefName("--");
                    callLogEntity.setRefType(CallCenterTypeEnum.UNKNOWN.getCode());
                }
            }

        }

        return callLogEntity;
    }

    private CallCenterCallLogEntity uinDtoToEntity(UinYunCallRecordDTO dto) throws XbbException {
        // 公司ID
        String corpid = dto.getCorpid();
        CallCenterCallLogEntity callLogEntity = new CallCenterCallLogEntity();
        BeanUtils.copyProperties(dto, callLogEntity);
        if (!Objects.equals("-1", callLogEntity.getUserId())) {
            UserEntity userEntity = userModel.getByKey(callLogEntity.getUserId(), corpid);
            if (Objects.nonNull(userEntity)) {
                callLogEntity.setUserName(userEntity.getName());
            }
        }
        // 客户号码
        String aliyunSteasPhoneNum = Objects.nonNull(dto.getType()) && dto.getType().equals(0) ? dto.getAgentPhoneNum() : dto.getAnotherPhoneNum();
        if (StringUtil.isNotEmpty(aliyunSteasPhoneNum)) {
            // 根据公司ID和电话查询线索
            CustomerEntityExt cusEntityExt = customerModel.getByPhoneIncloudRecycled(corpid, aliyunSteasPhoneNum);
            ContactEntityExt contactEntityExt = null;
            if (Objects.nonNull(cusEntityExt)) {
                callLogEntity.setRefId(cusEntityExt.getId());
                String name = FastJsonHelper.getStringOrDefaultFromFormData(cusEntityExt.getData(), CustomerManagementEnum.NAME.getAttr(), "");
                callLogEntity.setRefName(name);
                callLogEntity.setRefType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
            } else {
                // 联系人
                contactEntityExt = contactModel.getByPhone(corpid, aliyunSteasPhoneNum);
                if (Objects.nonNull(contactEntityExt)) {
                    Long contactId = contactEntityExt.getId();
                    callLogEntity.setRefId(contactId);
                    String name = FastJsonHelper.getStringOrDefaultFromFormData(contactEntityExt.getData(), ContactEnum.NAME.getAttr(), "");
                    callLogEntity.setRefName(name);
                    callLogEntity.setRefType(XbbRefTypeEnum.CONTACT.getCode());
                }
            }
            if (Objects.isNull(cusEntityExt) && Objects.isNull(contactEntityExt)) {
                // 线索
                ClueEntityExt clueEntityExt = clueModel.getByPhoneIncloudRecycled(corpid, aliyunSteasPhoneNum);
                if (Objects.nonNull(clueEntityExt)) {
                    Long clueId = clueEntityExt.getId();
                    callLogEntity.setRefId(clueId);
                    String name = FastJsonHelper.getStringOrDefaultFromFormData(clueEntityExt.getData(), ClueEnum.COMPANY_NAME.getAttr(), "");
                    callLogEntity.setRefName(name);
                    callLogEntity.setRefType(XbbRefTypeEnum.CLUE.getCode());
                } else {
                    callLogEntity.setRefId(0L);
                    callLogEntity.setRefName("--");
                    callLogEntity.setRefType(CallCenterTypeEnum.UNKNOWN.getCode());
                }
            }

        }

        return callLogEntity;
    }

    /**
     * 获取优音云通话记录查询参数
     *
     * @param pageDto 请求信息
     * @return es查询条件
     */
    private BoolQueryBuilder getYunQueryBuilder(YunCallPageRecordDTO pageDto) {
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, pageDto.getCorpid()));
        boolQueryBuilder.filter(termsQuery("callSource", CallCenterCallLogCallSourceEnum.listYunCallCallSource()));
        RangeQueryBuilder callTimeQuery = null;
        if (Objects.nonNull(pageDto.getStartTime())) {
            callTimeQuery = rangeQuery("callTime");
            callTimeQuery.gte(pageDto.getStartTime());
        }
        if (Objects.nonNull(pageDto.getEndTime())) {
            if(callTimeQuery == null){
                callTimeQuery = rangeQuery("callTime");
            }
            callTimeQuery.lt(pageDto.getEndTime());
        }
        if(callTimeQuery != null){
            boolQueryBuilder.filter(callTimeQuery);
        }
        if (StringUtils.isNotBlank(pageDto.getCallId())) {
            boolQueryBuilder.filter(termQuery("callId" + StringConstant.POINT + StringConstant.KEY_WORD, pageDto.getCallId()));
        }
        // 主叫号码
        String agentPhoneNum = pageDto.getAgentPhoneNum();
        // 查询被叫号码
        if (StringUtils.isNotBlank(agentPhoneNum)) {
            BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
            innerBoolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
            innerBoolQueryBuilder.should(matchPhraseQuery("agentPhoneNum", agentPhoneNum));
            boolQueryBuilder.filter(innerBoolQueryBuilder);
        }
        // 主叫号码
        String anotherPhoneNum = pageDto.getAnotherPhoneNum();
        // 查询主叫号码
        if (StringUtils.isNotBlank(anotherPhoneNum)) {
            BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
            innerBoolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
            innerBoolQueryBuilder.should(matchPhraseQuery("anotherPhoneNum", anotherPhoneNum));
            boolQueryBuilder.filter(innerBoolQueryBuilder);
        }
        // 员工
        if (StringUtils.isNotBlank(pageDto.getUserName())) {
            BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
            innerBoolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
            innerBoolQueryBuilder.should(matchPhraseQuery("userName", pageDto.getUserName()));
            boolQueryBuilder.filter(innerBoolQueryBuilder);
        }
        if (StringUtils.isNotBlank(pageDto.getSkillGroupNames())) {
            BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
            innerBoolQueryBuilder.should(matchPhraseQuery("skillGroupNames", pageDto.getSkillGroupNames()));
            innerBoolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
            boolQueryBuilder.filter(innerBoolQueryBuilder);
        }
        if (CollectionUtils.isNotEmpty(pageDto.getSearchUserIdList())) {
            boolQueryBuilder.filter(termsQuery("userId" + StringConstant.POINT + StringConstant.KEY_WORD, pageDto.getSearchUserIdList().toArray()));
        } if (StringUtils.isNotBlank(pageDto.getSearchUserId())) {
            boolQueryBuilder.filter(termQuery("userId" + StringConstant.POINT + StringConstant.KEY_WORD, pageDto.getSearchUserId()));
        }
        boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG;
        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
        return boolQueryBuilder;
    }

    /**
     * 获取优音云通话记录查询参数
     *
     * @param pageDto          请求信息
     * @param boolQueryBuilder boolQueryBuilder
     * @return 查询参数
     */
    public SearchSourceBuilder getUinYunSource(YunCallPageRecordDTO pageDto, BoolQueryBuilder boolQueryBuilder) {

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(boolQueryBuilder);
        // 根据排序字段进行排序
        if (StringUtils.isNotBlank(pageDto.getSortField()) && StringUtils.isNotBlank(pageDto.getSort())) {
            String sortField = getSortField(pageDto.getSortField());
            SortOrder sort = StringUtils.equalsIgnoreCase(pageDto.getSort(), SortOrder.DESC.toString()) ? SortOrder.DESC : SortOrder.ASC;
            sourceBuilder.sort(new FieldSortBuilder(sortField).order(sort));
        } else if (StringUtils.isNotBlank(pageDto.getSort())) {
            SortOrder sort = StringUtils.equalsIgnoreCase(pageDto.getSort(), SortOrder.DESC.toString()) ? SortOrder.DESC : SortOrder.ASC;
            sourceBuilder.sort(new FieldSortBuilder("addTime").order(sort));
        } else {
            sourceBuilder.sort(new FieldSortBuilder("addTime").order(SortOrder.DESC));
        }
        //设置查询路由
        SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG.getIndex());
        searchRequest.source(sourceBuilder);
        return sourceBuilder;
    }

    /**
     * 将某个用户对应的部门id放入部门id集合 departmentIdSet 中
     * @param department 某个用户所在的部门id数组，[1,2]格式
     * @param departmentIdSet 部门id集合
     */
    private void formatDepIdSet(String department, Set<Long> departmentIdSet) {
        if (StringUtil.isEmpty(department)) {
            // department为空 异常数据可以记点日志
            return;
        }
        JSONArray depArr = JSON.parseArray(department);
        if(depArr != null && depArr.size() > 0) {
            for (int i = 0; i < depArr.size(); i++) {
                try{
                    Long depId = depArr.getLong(i);
                    departmentIdSet.add(depId);
                } catch (JSONException je) {
                    LOG.error("department 字段格式错误", je);
                }
            }
        }
    }

    /**
     * 获取呼出统计
     *
     * @param dto      dao
     * @param recordVO recordVO
     * @throws XbbException 异常
     */
    private void getOutboundCount(UinSumCallRecordDTO dto, UinSumCallRecordVO recordVO) throws XbbException {
        BoolQueryBuilder outboundBuilder = getUinSumQueryBuilder(dto);
        outboundBuilder.filter(rangeQuery("type").gte(BasicConstant.ONE).lte(BasicConstant.ONE));
        //求和字段
        String sumField = "duration";
        //统计
        TotalAndAggPojo aggPojo = systemChartHelp.getInt4Total(IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG, outboundBuilder, sumField);
        int code = CallLogResultEnum.SUCCESS.getCode();
        outboundBuilder.filter(rangeQuery("answer").gte(code).lte(code));
        ElasticAggsPojo elasticAggsPojo = esHelper.elasticAggs(IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG, outboundBuilder, null);
        //今日呼出数
        int count = aggPojo.getTotal();
        //今日呼出时长
        int agg = aggPojo.getAgg();
        BigDecimal outTime = BigDecimal.valueOf(agg);
        double div = Math.ceil(outTime.divide(BigDecimal.valueOf(60), 7, RoundingMode.CEILING).doubleValue());
        recordVO.setTotalOutboundTalkTime((int) div);
        recordVO.setCallsDialed(count);
        recordVO.setCallsAnswered(StringUtil.toInt(elasticAggsPojo.getTotal()));
    }

    /**
     * 获取呼入统计
     *
     * @param dto      dao
     * @param recordVO recordVO
     * @throws XbbException 异常
     */
    private void getInboundCount(UinSumCallRecordDTO dto, UinSumCallRecordVO recordVO) throws XbbException {
        BoolQueryBuilder outboundBuilder = getUinSumQueryBuilder(dto);
        outboundBuilder.filter(rangeQuery("type").gte(BasicConstant.ZERO).lte(BasicConstant.ZERO));
        //求和字段
        String sumField = "duration";
        //统计
        TotalAndAggPojo aggPojo = systemChartHelp.getInt4Total(IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG, outboundBuilder, sumField);
        int code = CallLogResultEnum.SUCCESS.getCode();
        outboundBuilder.filter(rangeQuery("answer").gte(code).lte(code));
        ElasticAggsPojo elasticAggsPojo = esHelper.elasticAggs(IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG, outboundBuilder, null);
        //今日呼入数
        int count = aggPojo.getTotal();
        //今日呼入时长
        int agg = aggPojo.getAgg();
        BigDecimal inTime = BigDecimal.valueOf(agg);
        double div = Math.ceil(inTime.divide(BigDecimal.valueOf(60), 7, RoundingMode.CEILING).doubleValue());
        recordVO.setTotalInboundTalkTime((int) div);
        recordVO.setCallsOffered(count);
        recordVO.setCallsHandled(StringUtil.toInt(elasticAggsPojo.getTotal()));
    }


    /**
     * 获取呼出统计
     *
     * @param dto      dao
     * @param recordVO recordVO
     * @throws XbbException 异常
     */
    private void getOutboundCount(ExternalSumCallRecordDTO dto, ExternalSumCallRecordVO recordVO) throws XbbException {
        BoolQueryBuilder outboundBuilder = getUinSumQueryBuilder(dto);
        outboundBuilder.filter(rangeQuery("type").gte(BasicConstant.ONE).lte(BasicConstant.ONE));
        //求和字段
        String sumField = "duration";
        //统计
        TotalAndAggPojo aggPojo = systemChartHelp.getInt4Total(IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG, outboundBuilder, sumField);
        int code = CallLogResultEnum.SUCCESS.getCode();
        outboundBuilder.filter(rangeQuery("answer").gte(code).lte(code));
        ElasticAggsPojo elasticAggsPojo = esHelper.elasticAggs(IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG, outboundBuilder, null);
        //今日呼出数
        int count = aggPojo.getTotal();
        //今日呼出时长
        int agg = aggPojo.getAgg();
        BigDecimal outTime = BigDecimal.valueOf(agg);
        double div = Math.ceil(outTime.divide(BigDecimal.valueOf(60), 7, RoundingMode.CEILING).doubleValue());
        recordVO.setTotalOutboundTalkTime((int) div);
        recordVO.setCallsDialed(count);
        recordVO.setCallsAnswered(StringUtil.toInt(elasticAggsPojo.getTotal()));
    }

    /**
     * 获取呼入统计
     *
     * @param dto      dao
     * @param recordVO recordVO
     * @throws XbbException 异常
     */
    private void getInboundCount(ExternalSumCallRecordDTO dto, ExternalSumCallRecordVO recordVO) throws XbbException {
        BoolQueryBuilder outboundBuilder = getUinSumQueryBuilder(dto);
        outboundBuilder.filter(rangeQuery("type").gte(BasicConstant.ZERO).lte(BasicConstant.ZERO));
        //求和字段
        String sumField = "duration";
        //统计
        TotalAndAggPojo aggPojo = systemChartHelp.getInt4Total(IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG, outboundBuilder, sumField);
        int code = CallLogResultEnum.SUCCESS.getCode();
        outboundBuilder.filter(rangeQuery("answer").gte(code).lte(code));
        ElasticAggsPojo elasticAggsPojo = esHelper.elasticAggs(IndexTypeEnum.IDX_CALL_CENTER_CALL_LOG, outboundBuilder, null);
        //今日呼入数
        int count = aggPojo.getTotal();
        //今日呼入时长
        int agg = aggPojo.getAgg();
        BigDecimal inTime = BigDecimal.valueOf(agg);
        double div = Math.ceil(inTime.divide(BigDecimal.valueOf(60), 7, RoundingMode.CEILING).doubleValue());
        recordVO.setTotalInboundTalkTime((int) div);
        recordVO.setCallsOffered(count);
        recordVO.setCallsHandled(StringUtil.toInt(elasticAggsPojo.getTotal()));
    }



    /**
     * 获取优音的查询条件
     *
     * @param dto 查询
     * @return 查询条件
     */
    private BoolQueryBuilder getUinSumQueryBuilder(UinSumCallRecordDTO dto){
        // 公司ID
        String corpid = dto.getCorpid();
        // 用户ID
        String userId = dto.getUserId();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termQuery("userId.keyword", userId));
        Integer code = CallCenterCallLogCallSourceEnum.UIN_YUN_CALL.getCode();
        boolQueryBuilder.filter(rangeQuery("callSource").gte(code).lte(code));
        boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        return boolQueryBuilder;
    }

    /**
     * 获取外接的查询条件
     *
     * @param dto 查询
     * @return 查询条件
     */
    private BoolQueryBuilder getUinSumQueryBuilder(ExternalSumCallRecordDTO dto){
        // 公司ID
        String corpid = dto.getCorpid();
        // 用户ID
        String userId = dto.getUserId();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termQuery("userId.keyword", userId));
        Integer code = CallCenterCallLogCallSourceEnum.EXTERNAL_SYSTEM.getCode();
        boolQueryBuilder.filter(rangeQuery("callSource").gte(code).lte(code));
        boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        return boolQueryBuilder;
    }


}
